151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.security.ssl;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.ByteArrayOutputStream;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.*;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Arrays;
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.LinkedList;
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.List;
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Locale;
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Set;
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Abstraction for the SSL/TLS hash of all handshake messages that is
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * maintained to verify the integrity of the negotiation. Internally,
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * it consists of an MD5 and an SHA1 digest. They are used in the client
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and server finished messages and in certificate verify messages (if sent).
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This class transparently deals with cloneable and non-cloneable digests.
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This class now supports TLS 1.2 also. The key difference for TLS 1.2
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is that you cannot determine the hash algorithms for CertificateVerify
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * at a early stage. On the other hand, it's simpler than TLS 1.1 (and earlier)
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that there is no messy MD5+SHA1 digests.
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You need to obey these conventions when using this class:
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1. protocolDetermined(version) should be called when the negotiated
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * protocol version is determined.
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2. Before protocolDetermined() is called, only update(), reset(),
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * restrictCertificateVerifyAlgs(), setFinishedAlg(), and
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * setCertificateVerifyAlg() can be called.
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 3. After protocolDetermined() is called, reset() cannot be called.
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4. After protocolDetermined() is called, if the version is pre-TLS 1.2,
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * getFinishedHash() and getCertificateVerifyHash() cannot be called. Otherwise,
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * getMD5Clone() and getSHAClone() cannot be called.
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5. getMD5Clone() and getSHAClone() can only be called after
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * protocolDetermined() is called and version is pre-TLS 1.2.
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 6. getFinishedHash() and getCertificateVerifyHash() can only be called after
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * all protocolDetermined(), setCertificateVerifyAlg() and setFinishedAlg()
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * have been called and the version is TLS 1.2. If a CertificateVerify message
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is to be used, call setCertificateVerifyAlg() with the hash algorithm as the
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * argument. Otherwise, you still must call setCertificateVerifyAlg(null) before
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * calculating any hash value.
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Suggestions: Call protocolDetermined(), restrictCertificateVerifyAlgs(),
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * setFinishedAlg(), and setCertificateVerifyAlg() as early as possible.
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Example:
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre>
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * HandshakeHash hh = new HandshakeHash(...)
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * hh.protocolDetermined(ProtocolVersion.TLS12);
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * hh.update(clientHelloBytes);
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * hh.setFinishedAlg("SHA-256");
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * hh.update(serverHelloBytes);
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ...
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * hh.setCertificateVerifyAlg("SHA-384");
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * hh.update(CertificateVerifyBytes);
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * byte[] cvDigest = hh.getCertificateVerifyHash();
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ...
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * hh.update(finished1);
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * byte[] finDigest1 = hh.getFinishedHash();
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * hh.update(finished2);
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * byte[] finDigest2 = hh.getFinishedHash();
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre>
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If no CertificateVerify message is to be used, call
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre>
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * hh.setCertificateVerifyAlg(null);
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre>
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This call can be made once you are certain that this message
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * will never be used.
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskifinal class HandshakeHash {
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Common
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // -1:  unknown
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //  1:  <=TLS 1.1
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //  2:  TLS 1.2
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int version = -1;
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private ByteArrayOutputStream data = new ByteArrayOutputStream();
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final boolean isServer;
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // For TLS 1.1
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private MessageDigest md5, sha;
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final int clonesNeeded;    // needs to be saved for later use
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // For TLS 1.2
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // cvAlgDetermined == true means setCertificateVerifyAlg() is called
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean cvAlgDetermined = false;
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String cvAlg;
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private MessageDigest finMD;
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Create a new HandshakeHash. needCertificateVerify indicates whether
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * a hash for the certificate verify message is required. The argument
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * algs is a set of all possible hash algorithms that might be used in
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * TLS 1.2. If the caller is sure that TLS 1.2 won't be used or no
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * CertificateVerify message will be used, leave it null or empty.
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    HandshakeHash(boolean isServer, boolean needCertificateVerify,
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Set<String> algs) {
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.isServer = isServer;
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        clonesNeeded = needCertificateVerify ? 3 : 2;
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void update(byte[] b, int offset, int len) {
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        switch (version) {
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case 1:
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                md5.update(b, offset, len);
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                sha.update(b, offset, len);
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            default:
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (finMD != null) {
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    finMD.update(b, offset, len);
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                data.write(b, offset, len);
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reset the remaining digests. Note this does *not* reset the number of
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * digest clones that can be obtained. Digests that have already been
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * cloned and are gone remain gone.
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void reset() {
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (version != -1) {
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new RuntimeException(
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    "reset() can be only be called before protocolDetermined");
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        data.reset();
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void protocolDetermined(ProtocolVersion pv) {
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Do not set again, will ignore
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (version != -1) return;
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        version = pv.compareTo(ProtocolVersion.TLS12) >= 0 ? 2 : 1;
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        switch (version) {
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case 1:
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // initiate md5, sha and call update on saved array
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                try {
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    md5 = CloneableDigest.getDigest("MD5", clonesNeeded);
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    sha = CloneableDigest.getDigest("SHA", clonesNeeded);
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } catch (NoSuchAlgorithmException e) {
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new RuntimeException
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                ("Algorithm MD5 or SHA not available", e);
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                byte[] bytes = data.toByteArray();
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                update(bytes, 0, bytes.length);
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case 2:
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /////////////////////////////////////////////////////////////
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Below are old methods for pre-TLS 1.1
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /////////////////////////////////////////////////////////////
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Return a new MD5 digest updated with all data hashed so far.
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    MessageDigest getMD5Clone() {
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (version != 1) {
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new RuntimeException(
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    "getMD5Clone() can be only be called for TLS 1.1");
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return cloneDigest(md5);
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Return a new SHA digest updated with all data hashed so far.
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    MessageDigest getSHAClone() {
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (version != 1) {
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new RuntimeException(
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    "getSHAClone() can be only be called for TLS 1.1");
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return cloneDigest(sha);
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static MessageDigest cloneDigest(MessageDigest digest) {
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (MessageDigest)digest.clone();
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (CloneNotSupportedException e) {
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // cannot occur for digests generated via CloneableDigest
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new RuntimeException("Could not clone digest", e);
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /////////////////////////////////////////////////////////////
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Below are new methods for TLS 1.2
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /////////////////////////////////////////////////////////////
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static String normalizeAlgName(String alg) {
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        alg = alg.toUpperCase(Locale.US);
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (alg.startsWith("SHA")) {
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (alg.length() == 3) {
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return "SHA-1";
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (alg.charAt(3) != '-') {
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return "SHA-" + alg.substring(3);
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return alg;
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Specifies the hash algorithm used in Finished. This should be called
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * based in info in ServerHello.
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Can be called multiple times.
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void setFinishedAlg(String s) {
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (s == null) {
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new RuntimeException(
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    "setFinishedAlg's argument cannot be null");
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Can be called multiple times, but only set once
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (finMD != null) return;
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            finMD = CloneableDigest.getDigest(normalizeAlgName(s), 2);
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (NoSuchAlgorithmException e) {
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new Error(e);
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        finMD.update(data.toByteArray());
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Restricts the possible algorithms for the CertificateVerify. Called by
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the server based on info in CertRequest. The argument must be a subset
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * of the argument with the same name in the constructor. The method can be
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * called multiple times. If the caller is sure that no CertificateVerify
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * message will be used, leave this argument null or empty.
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void restrictCertificateVerifyAlgs(Set<String> algs) {
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (version == 1) {
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new RuntimeException(
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    "setCertificateVerifyAlg() cannot be called for TLS 1.1");
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Not used yet
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Specifies the hash algorithm used in CertificateVerify.
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Can be called multiple times.
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void setCertificateVerifyAlg(String s) {
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Can be called multiple times, but only set once
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cvAlgDetermined) return;
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        cvAlg = s == null ? null : normalizeAlgName(s);
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        cvAlgDetermined = true;
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    byte[] getAllHandshakeMessages() {
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return data.toByteArray();
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Calculates the hash in the CertificateVerify. Must be called right
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * after setCertificateVerifyAlg()
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*byte[] getCertificateVerifyHash() {
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throw new Error("Do not call getCertificateVerifyHash()");
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }*/
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Calculates the hash in Finished. Must be called after setFinishedAlg().
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method can be called twice, for Finished messages of the server
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * side and client side respectively.
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    byte[] getFinishedHash() {
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return cloneDigest(finMD).digest();
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new Error("BAD");
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A wrapper for MessageDigests that simulates cloning of non-cloneable
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * digests. It uses the standard MessageDigest API and therefore can be used
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * transparently in place of a regular digest.
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Note that we extend the MessageDigest class directly rather than
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * MessageDigestSpi. This works because MessageDigest was originally designed
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this way in the JDK 1.1 days which allows us to avoid creating an internal
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * provider.
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * It can be "cloned" a limited number of times, which is specified at
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * construction time. This is achieved by internally maintaining n digests
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in parallel. Consequently, it is only 1/n-th times as fast as the original
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * digest.
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Example:
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   MessageDigest md = CloneableDigest.getDigest("SHA", 2);
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   md.update(data1);
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   MessageDigest md2 = (MessageDigest)md.clone();
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   md2.update(data2);
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   byte[] d1 = md2.digest(); // digest of data1 || data2
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   md.update(data3);
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   byte[] d2 = md.digest();  // digest of data1 || data3
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This class is not thread safe.
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskifinal class CloneableDigest extends MessageDigest implements Cloneable {
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The individual MessageDigests. Initially, all elements are non-null.
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * When clone() is called, the non-null element with the maximum index is
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * returned and the array element set to null.
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * All non-null element are always in the same state.
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final MessageDigest[] digests;
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private CloneableDigest(MessageDigest digest, int n, String algorithm)
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws NoSuchAlgorithmException {
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        super(algorithm);
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        digests = new MessageDigest[n];
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        digests[0] = digest;
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 1; i < n; i++) {
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            digests[i] = JsseJce.getMessageDigest(algorithm);
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Return a MessageDigest for the given algorithm that can be cloned the
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * specified number of times. If the default implementation supports
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * cloning, it is returned. Otherwise, an instance of this class is
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * returned.
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static MessageDigest getDigest(String algorithm, int n)
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws NoSuchAlgorithmException {
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        MessageDigest digest = JsseJce.getMessageDigest(algorithm);
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            digest.clone();
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // already cloneable, use it
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return digest;
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (CloneNotSupportedException e) {
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return new CloneableDigest(digest, n, algorithm);
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Check if this object is still usable. If it has already been cloned the
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * maximum number of times, there are no digests left and this object can no
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * longer be used.
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void checkState() {
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // XXX handshaking currently doesn't stop updating hashes...
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // if (digests[0] == null) {
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        //     throw new IllegalStateException("no digests left");
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // }
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected int engineGetDigestLength() {
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        checkState();
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return digests[0].getDigestLength();
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void engineUpdate(byte b) {
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        checkState();
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            digests[i].update(b);
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void engineUpdate(byte[] b, int offset, int len) {
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        checkState();
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            digests[i].update(b, offset, len);
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected byte[] engineDigest() {
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        checkState();
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        byte[] digest = digests[0].digest();
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        digestReset();
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return digest;
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected int engineDigest(byte[] buf, int offset, int len)
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws DigestException {
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        checkState();
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int n = digests[0].digest(buf, offset, len);
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        digestReset();
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return n;
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reset all digests after a digest() call. digests[0] has already been
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * implicitly reset by the digest() call and does not need to be reset
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * again.
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void digestReset() {
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 1; (i < digests.length) && (digests[i] != null); i++) {
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            digests[i].reset();
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void engineReset() {
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        checkState();
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            digests[i].reset();
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Object clone() {
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        checkState();
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = digests.length - 1; i >= 0; i--) {
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (digests[i] != null) {
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                MessageDigest digest = digests[i];
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                digests[i] = null;
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return digest;
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // cannot occur
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throw new InternalError();
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
460