src/java.base/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 56541 92cbbfc996f3
child 56543 2352538d2f6e
--- a/src/java.base/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java	Fri May 11 14:55:56 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,441 +0,0 @@
-/*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.security.AlgorithmConstraints;
-import java.security.CryptoPrimitive;
-import java.security.PrivateKey;
-import java.security.Security;
-
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.EnumSet;
-import java.util.TreeMap;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.ArrayList;
-
-import sun.security.util.KeyUtil;
-
-/**
- * Signature and hash algorithm.
- *
- * [RFC5246] The client uses the "signature_algorithms" extension to
- * indicate to the server which signature/hash algorithm pairs may be
- * used in digital signatures.  The "extension_data" field of this
- * extension contains a "supported_signature_algorithms" value.
- *
- *     enum {
- *         none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
- *         sha512(6), (255)
- *     } HashAlgorithm;
- *
- *     enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
- *       SignatureAlgorithm;
- *
- *     struct {
- *           HashAlgorithm hash;
- *           SignatureAlgorithm signature;
- *     } SignatureAndHashAlgorithm;
- */
-final class SignatureAndHashAlgorithm {
-
-    // minimum priority for default enabled algorithms
-    static final int SUPPORTED_ALG_PRIORITY_MAX_NUM = 0x00F0;
-
-    // performance optimization
-    private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
-        Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
-
-    // supported pairs of signature and hash algorithm
-    private static final Map<Integer, SignatureAndHashAlgorithm> supportedMap;
-    private static final Map<Integer, SignatureAndHashAlgorithm> priorityMap;
-
-    // the hash algorithm
-    private HashAlgorithm hash;
-
-    // id in 16 bit MSB format, i.e. 0x0603 for SHA512withECDSA
-    private int id;
-
-    // the standard algorithm name, for example "SHA512withECDSA"
-    private String algorithm;
-
-    // Priority for the preference order. The lower the better.
-    //
-    // If the algorithm is unsupported, its priority should be bigger
-    // than SUPPORTED_ALG_PRIORITY_MAX_NUM.
-    private int priority;
-
-    // constructor for supported algorithm
-    private SignatureAndHashAlgorithm(HashAlgorithm hash,
-            SignatureAlgorithm signature, String algorithm, int priority) {
-        this.hash = hash;
-        this.algorithm = algorithm;
-        this.id = ((hash.value & 0xFF) << 8) | (signature.value & 0xFF);
-        this.priority = priority;
-    }
-
-    // constructor for unsupported algorithm
-    private SignatureAndHashAlgorithm(String algorithm, int id, int sequence) {
-        this.hash = HashAlgorithm.valueOf((id >> 8) & 0xFF);
-        this.algorithm = algorithm;
-        this.id = id;
-
-        // add one more to the sequence number, in case that the number is zero
-        this.priority = SUPPORTED_ALG_PRIORITY_MAX_NUM + sequence + 1;
-    }
-
-    // Note that we do not use the sequence argument for supported algorithms,
-    // so please don't sort by comparing the objects read from handshake
-    // messages.
-    static SignatureAndHashAlgorithm valueOf(int hash,
-            int signature, int sequence) {
-        hash &= 0xFF;
-        signature &= 0xFF;
-
-        int id = (hash << 8) | signature;
-        SignatureAndHashAlgorithm signAlg = supportedMap.get(id);
-        if (signAlg == null) {
-            // unsupported algorithm
-            signAlg = new SignatureAndHashAlgorithm(
-                "Unknown (hash:0x" + Integer.toString(hash, 16) +
-                ", signature:0x" + Integer.toString(signature, 16) + ")",
-                id, sequence);
-        }
-
-        return signAlg;
-    }
-
-    int getHashValue() {
-        return (id >> 8) & 0xFF;
-    }
-
-    int getSignatureValue() {
-        return id & 0xFF;
-    }
-
-    String getAlgorithmName() {
-        return algorithm;
-    }
-
-    // return the size of a SignatureAndHashAlgorithm structure in TLS record
-    static int sizeInRecord() {
-        return 2;
-    }
-
-    // Get local supported algorithm collection complying to
-    // algorithm constraints
-    static Collection<SignatureAndHashAlgorithm>
-            getSupportedAlgorithms(AlgorithmConstraints constraints) {
-
-        Collection<SignatureAndHashAlgorithm> supported = new ArrayList<>();
-        for (SignatureAndHashAlgorithm sigAlg : priorityMap.values()) {
-            if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM &&
-                    constraints.permits(SIGNATURE_PRIMITIVE_SET,
-                            sigAlg.algorithm, null)) {
-                supported.add(sigAlg);
-            }
-        }
-
-        return supported;
-    }
-
-    // Get supported algorithm collection from an untrusted collection
-    static Collection<SignatureAndHashAlgorithm> getSupportedAlgorithms(
-            AlgorithmConstraints constraints,
-            Collection<SignatureAndHashAlgorithm> algorithms ) {
-        Collection<SignatureAndHashAlgorithm> supported = new ArrayList<>();
-        for (SignatureAndHashAlgorithm sigAlg : algorithms) {
-            if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM &&
-                    constraints.permits(SIGNATURE_PRIMITIVE_SET,
-                                sigAlg.algorithm, null)) {
-                supported.add(sigAlg);
-            }
-        }
-
-        return supported;
-    }
-
-    static String[] getAlgorithmNames(
-            Collection<SignatureAndHashAlgorithm> algorithms) {
-        ArrayList<String> algorithmNames = new ArrayList<>();
-        if (algorithms != null) {
-            for (SignatureAndHashAlgorithm sigAlg : algorithms) {
-                algorithmNames.add(sigAlg.algorithm);
-            }
-        }
-
-        String[] array = new String[algorithmNames.size()];
-        return algorithmNames.toArray(array);
-    }
-
-    static Set<String> getHashAlgorithmNames(
-            Collection<SignatureAndHashAlgorithm> algorithms) {
-        Set<String> algorithmNames = new HashSet<>();
-        if (algorithms != null) {
-            for (SignatureAndHashAlgorithm sigAlg : algorithms) {
-                if (sigAlg.hash.value > 0) {
-                    algorithmNames.add(sigAlg.hash.standardName);
-                }
-            }
-        }
-
-        return algorithmNames;
-    }
-
-    static String getHashAlgorithmName(SignatureAndHashAlgorithm algorithm) {
-        return algorithm.hash.standardName;
-    }
-
-    private static void supports(HashAlgorithm hash,
-            SignatureAlgorithm signature, String algorithm, int priority) {
-
-        SignatureAndHashAlgorithm pair =
-            new SignatureAndHashAlgorithm(hash, signature, algorithm, priority);
-        if (supportedMap.put(pair.id, pair) != null) {
-            throw new RuntimeException(
-                "Duplicate SignatureAndHashAlgorithm definition, id: " +
-                pair.id);
-        }
-        if (priorityMap.put(pair.priority, pair) != null) {
-            throw new RuntimeException(
-                "Duplicate SignatureAndHashAlgorithm definition, priority: " +
-                pair.priority);
-        }
-    }
-
-    static SignatureAndHashAlgorithm getPreferableAlgorithm(
-        Collection<SignatureAndHashAlgorithm> algorithms, String expected) {
-
-        return SignatureAndHashAlgorithm.getPreferableAlgorithm(
-                algorithms, expected, null);
-    }
-
-    static SignatureAndHashAlgorithm getPreferableAlgorithm(
-            Collection<SignatureAndHashAlgorithm> algorithms,
-            String expected, PrivateKey signingKey) {
-
-        int maxDigestLength = getMaxDigestLength(signingKey);
-        for (SignatureAndHashAlgorithm algorithm : algorithms) {
-            int signValue = algorithm.id & 0xFF;
-            if ((expected == null) ||
-                    (expected.equalsIgnoreCase("rsa") &&
-                            signValue == SignatureAlgorithm.RSA.value) ||
-                    (expected.equalsIgnoreCase("dsa") &&
-                            signValue == SignatureAlgorithm.DSA.value) ||
-                    (expected.equalsIgnoreCase("ecdsa") &&
-                            signValue == SignatureAlgorithm.ECDSA.value) ||
-                    (expected.equalsIgnoreCase("ec") &&
-                            signValue == SignatureAlgorithm.ECDSA.value)) {
-
-                if (algorithm.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM &&
-                        algorithm.hash.length <= maxDigestLength) {
-
-                    return algorithm;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    /*
-     * Need to check key length to match the length of hash value
-     */
-    private static int getMaxDigestLength(PrivateKey signingKey) {
-        int maxDigestLength = Integer.MAX_VALUE;
-
-        // only need to check RSA algorithm at present.
-        if (signingKey != null &&
-                "rsa".equalsIgnoreCase(signingKey.getAlgorithm())) {
-            /*
-             * RSA keys of 512 bits have been shown to be practically
-             * breakable, it does not make much sense to use the strong
-             * hash algorithm for keys whose key size less than 512 bits.
-             * So it is not necessary to caculate the required max digest
-             * length exactly.
-             *
-             * If key size is greater than or equals to 768, there is no max
-             * digest length limitation in currect implementation.
-             *
-             * If key size is greater than or equals to 512, but less than
-             * 768, the digest length should be less than or equal to 32 bytes.
-             *
-             * If key size is less than 512, the  digest length should be
-             * less than or equal to 20 bytes.
-             */
-            int keySize = KeyUtil.getKeySize(signingKey);
-            if (keySize >= 768) {
-                maxDigestLength = HashAlgorithm.SHA512.length;
-            } else if ((keySize >= 512) && (keySize < 768)) {
-                maxDigestLength = HashAlgorithm.SHA256.length;
-            } else if ((keySize > 0) && (keySize < 512)) {
-                maxDigestLength = HashAlgorithm.SHA1.length;
-            }   // Otherwise, cannot determine the key size, prefer the most
-                // preferable hash algorithm.
-        }
-
-        return maxDigestLength;
-    }
-
-    static enum HashAlgorithm {
-        UNDEFINED("undefined",        "", -1, -1),
-        NONE(          "none",    "NONE",  0, -1),
-        MD5(            "md5",     "MD5",  1, 16),
-        SHA1(          "sha1",   "SHA-1",  2, 20),
-        SHA224(      "sha224", "SHA-224",  3, 28),
-        SHA256(      "sha256", "SHA-256",  4, 32),
-        SHA384(      "sha384", "SHA-384",  5, 48),
-        SHA512(      "sha512", "SHA-512",  6, 64);
-
-        final String name;  // not the standard signature algorithm name
-                            // except the UNDEFINED, other names are defined
-                            // by TLS 1.2 protocol
-        final String standardName; // the standard MessageDigest algorithm name
-        final int value;
-        final int length;   // digest length in bytes, -1 means not applicable
-
-        private HashAlgorithm(String name, String standardName,
-                int value, int length) {
-            this.name = name;
-            this.standardName = standardName;
-            this.value = value;
-            this.length = length;
-        }
-
-        static HashAlgorithm valueOf(int value) {
-            HashAlgorithm algorithm = UNDEFINED;
-            switch (value) {
-                case 0:
-                    algorithm = NONE;
-                    break;
-                case 1:
-                    algorithm = MD5;
-                    break;
-                case 2:
-                    algorithm = SHA1;
-                    break;
-                case 3:
-                    algorithm = SHA224;
-                    break;
-                case 4:
-                    algorithm = SHA256;
-                    break;
-                case 5:
-                    algorithm = SHA384;
-                    break;
-                case 6:
-                    algorithm = SHA512;
-                    break;
-            }
-
-            return algorithm;
-        }
-    }
-
-    static enum SignatureAlgorithm {
-        UNDEFINED("undefined", -1),
-        ANONYMOUS("anonymous",  0),
-        RSA(            "rsa",  1),
-        DSA(            "dsa",  2),
-        ECDSA(        "ecdsa",  3);
-
-        final String name;  // not the standard signature algorithm name
-                            // except the UNDEFINED, other names are defined
-                            // by TLS 1.2 protocol
-        final int value;
-
-        private SignatureAlgorithm(String name, int value) {
-            this.name = name;
-            this.value = value;
-        }
-
-        static SignatureAlgorithm valueOf(int value) {
-            SignatureAlgorithm algorithm = UNDEFINED;
-            switch (value) {
-                case 0:
-                    algorithm = ANONYMOUS;
-                    break;
-                case 1:
-                    algorithm = RSA;
-                    break;
-                case 2:
-                    algorithm = DSA;
-                    break;
-                case 3:
-                    algorithm = ECDSA;
-                    break;
-            }
-
-            return algorithm;
-        }
-    }
-
-    static {
-        supportedMap = Collections.synchronizedSortedMap(
-            new TreeMap<Integer, SignatureAndHashAlgorithm>());
-        priorityMap = Collections.synchronizedSortedMap(
-            new TreeMap<Integer, SignatureAndHashAlgorithm>());
-
-        synchronized (supportedMap) {
-            int p = SUPPORTED_ALG_PRIORITY_MAX_NUM;
-            supports(HashAlgorithm.MD5,         SignatureAlgorithm.RSA,
-                    "MD5withRSA",           --p);
-            supports(HashAlgorithm.SHA1,        SignatureAlgorithm.DSA,
-                    "SHA1withDSA",          --p);
-            supports(HashAlgorithm.SHA1,        SignatureAlgorithm.RSA,
-                    "SHA1withRSA",          --p);
-            supports(HashAlgorithm.SHA1,        SignatureAlgorithm.ECDSA,
-                    "SHA1withECDSA",        --p);
-
-            if (Security.getProvider("SunMSCAPI") == null) {
-                supports(HashAlgorithm.SHA224,      SignatureAlgorithm.DSA,
-                        "SHA224withDSA",        --p);
-                supports(HashAlgorithm.SHA224,      SignatureAlgorithm.RSA,
-                        "SHA224withRSA",        --p);
-                supports(HashAlgorithm.SHA224,      SignatureAlgorithm.ECDSA,
-                        "SHA224withECDSA",      --p);
-            }
-
-            supports(HashAlgorithm.SHA256,      SignatureAlgorithm.DSA,
-                    "SHA256withDSA",        --p);
-            supports(HashAlgorithm.SHA256,      SignatureAlgorithm.RSA,
-                    "SHA256withRSA",        --p);
-            supports(HashAlgorithm.SHA256,      SignatureAlgorithm.ECDSA,
-                    "SHA256withECDSA",      --p);
-            supports(HashAlgorithm.SHA384,      SignatureAlgorithm.RSA,
-                    "SHA384withRSA",        --p);
-            supports(HashAlgorithm.SHA384,      SignatureAlgorithm.ECDSA,
-                    "SHA384withECDSA",      --p);
-            supports(HashAlgorithm.SHA512,      SignatureAlgorithm.RSA,
-                    "SHA512withRSA",        --p);
-            supports(HashAlgorithm.SHA512,      SignatureAlgorithm.ECDSA,
-                    "SHA512withECDSA",      --p);
-        }
-    }
-}
-