1 /*
   2  * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.ssl;
  27 
  28 import java.security.AlgorithmConstraints;
  29 import java.security.CryptoPrimitive;
  30 import java.security.AlgorithmParameters;
  31 
  32 import javax.net.ssl.*;
  33 
  34 import java.security.Key;
  35 
  36 import java.util.Set;
  37 
  38 import sun.security.util.DisabledAlgorithmConstraints;
  39 import static sun.security.util.DisabledAlgorithmConstraints.*;
  40 import sun.security.ssl.CipherSuite.*;
  41 
  42 /**
  43  * Algorithm constraints for disabled algorithms property
  44  *
  45  * See the "jdk.certpath.disabledAlgorithms" specification in java.security
  46  * for the syntax of the disabled algorithm string.
  47  */
  48 final class SSLAlgorithmConstraints implements AlgorithmConstraints {
  49 
  50     private static final AlgorithmConstraints tlsDisabledAlgConstraints =
  51             new DisabledAlgorithmConstraints(PROPERTY_TLS_DISABLED_ALGS,
  52                     new SSLAlgorithmDecomposer());
  53 
  54     private static final AlgorithmConstraints x509DisabledAlgConstraints =
  55             new DisabledAlgorithmConstraints(PROPERTY_CERTPATH_DISABLED_ALGS,
  56                     new SSLAlgorithmDecomposer(true));
  57 
  58     private AlgorithmConstraints userAlgConstraints = null;
  59     private AlgorithmConstraints peerAlgConstraints = null;
  60 
  61     private boolean enabledX509DisabledAlgConstraints = true;
  62 
  63     // the default algorithm constraints
  64     static final AlgorithmConstraints DEFAULT =
  65                         new SSLAlgorithmConstraints(null);
  66 
  67     // the default SSL only algorithm constraints
  68     static final AlgorithmConstraints DEFAULT_SSL_ONLY =
  69                         new SSLAlgorithmConstraints((SSLSocket)null, false);
  70 
  71     SSLAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) {
  72         userAlgConstraints = algorithmConstraints;
  73     }
  74 
  75     SSLAlgorithmConstraints(SSLSocket socket,
  76             boolean withDefaultCertPathConstraints) {
  77         if (socket != null) {
  78             userAlgConstraints =
  79                 socket.getSSLParameters().getAlgorithmConstraints();
  80         }
  81 
  82         if (!withDefaultCertPathConstraints) {
  83             enabledX509DisabledAlgConstraints = false;
  84         }
  85     }
  86 
  87     SSLAlgorithmConstraints(SSLEngine engine,
  88             boolean withDefaultCertPathConstraints) {
  89         if (engine != null) {
  90             userAlgConstraints =
  91                 engine.getSSLParameters().getAlgorithmConstraints();
  92         }
  93 
  94         if (!withDefaultCertPathConstraints) {
  95             enabledX509DisabledAlgConstraints = false;
  96         }
  97     }
  98 
  99     SSLAlgorithmConstraints(SSLSocket socket, String[] supportedAlgorithms,
 100             boolean withDefaultCertPathConstraints) {
 101         if (socket != null) {
 102             userAlgConstraints =
 103                 socket.getSSLParameters().getAlgorithmConstraints();
 104             peerAlgConstraints =
 105                 new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
 106         }
 107 
 108         if (!withDefaultCertPathConstraints) {
 109             enabledX509DisabledAlgConstraints = false;
 110         }
 111     }
 112 
 113     SSLAlgorithmConstraints(SSLEngine engine, String[] supportedAlgorithms,
 114             boolean withDefaultCertPathConstraints) {
 115         if (engine != null) {
 116             userAlgConstraints =
 117                 engine.getSSLParameters().getAlgorithmConstraints();
 118             peerAlgConstraints =
 119                 new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
 120         }
 121 
 122         if (!withDefaultCertPathConstraints) {
 123             enabledX509DisabledAlgConstraints = false;
 124         }
 125     }
 126 
 127     @Override
 128     public boolean permits(Set<CryptoPrimitive> primitives,
 129             String algorithm, AlgorithmParameters parameters) {
 130 
 131         boolean permitted = true;
 132 
 133         if (peerAlgConstraints != null) {
 134             permitted = peerAlgConstraints.permits(
 135                                     primitives, algorithm, parameters);
 136         }
 137 
 138         if (permitted && userAlgConstraints != null) {
 139             permitted = userAlgConstraints.permits(
 140                                     primitives, algorithm, parameters);
 141         }
 142 
 143         if (permitted) {
 144             permitted = tlsDisabledAlgConstraints.permits(
 145                                     primitives, algorithm, parameters);
 146         }
 147 
 148         if (permitted && enabledX509DisabledAlgConstraints) {
 149             permitted = x509DisabledAlgConstraints.permits(
 150                                     primitives, algorithm, parameters);
 151         }
 152 
 153         return permitted;
 154     }
 155 
 156     @Override
 157     public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
 158 
 159         boolean permitted = true;
 160 
 161         if (peerAlgConstraints != null) {
 162             permitted = peerAlgConstraints.permits(primitives, key);
 163         }
 164 
 165         if (permitted && userAlgConstraints != null) {
 166             permitted = userAlgConstraints.permits(primitives, key);
 167         }
 168 
 169         if (permitted) {
 170             permitted = tlsDisabledAlgConstraints.permits(primitives, key);
 171         }
 172 
 173         if (permitted && enabledX509DisabledAlgConstraints) {
 174             permitted = x509DisabledAlgConstraints.permits(primitives, key);
 175         }
 176 
 177         return permitted;
 178     }
 179 
 180     @Override
 181     public boolean permits(Set<CryptoPrimitive> primitives,
 182             String algorithm, Key key, AlgorithmParameters parameters) {
 183 
 184         boolean permitted = true;
 185 
 186         if (peerAlgConstraints != null) {
 187             permitted = peerAlgConstraints.permits(
 188                                     primitives, algorithm, key, parameters);
 189         }
 190 
 191         if (permitted && userAlgConstraints != null) {
 192             permitted = userAlgConstraints.permits(
 193                                     primitives, algorithm, key, parameters);
 194         }
 195 
 196         if (permitted) {
 197             permitted = tlsDisabledAlgConstraints.permits(
 198                                     primitives, algorithm, key, parameters);
 199         }
 200 
 201         if (permitted && enabledX509DisabledAlgConstraints) {
 202             permitted = x509DisabledAlgConstraints.permits(
 203                                     primitives, algorithm, key, parameters);
 204         }
 205 
 206         return permitted;
 207     }
 208 
 209 
 210     private static class SupportedSignatureAlgorithmConstraints
 211                                     implements AlgorithmConstraints {
 212         // supported signature algorithms
 213         private String[] supportedAlgorithms;
 214 
 215         SupportedSignatureAlgorithmConstraints(String[] supportedAlgorithms) {
 216             if (supportedAlgorithms != null) {
 217                 this.supportedAlgorithms = supportedAlgorithms.clone();
 218             } else {
 219                 this.supportedAlgorithms = null;
 220             }
 221         }
 222 
 223         @Override
 224         public boolean permits(Set<CryptoPrimitive> primitives,
 225                 String algorithm, AlgorithmParameters parameters) {
 226 
 227             if (algorithm == null || algorithm.length() == 0) {
 228                 throw new IllegalArgumentException(
 229                         "No algorithm name specified");
 230             }
 231 
 232             if (primitives == null || primitives.isEmpty()) {
 233                 throw new IllegalArgumentException(
 234                         "No cryptographic primitive specified");
 235             }
 236 
 237             if (supportedAlgorithms == null ||
 238                         supportedAlgorithms.length == 0) {
 239                 return false;
 240             }
 241 
 242             // trim the MGF part: <digest>with<encryption>and<mgf>
 243             int position = algorithm.indexOf("and");
 244             if (position > 0) {
 245                 algorithm = algorithm.substring(0, position);
 246             }
 247 
 248             for (String supportedAlgorithm : supportedAlgorithms) {
 249                 if (algorithm.equalsIgnoreCase(supportedAlgorithm)) {
 250                     return true;
 251                 }
 252             }
 253 
 254             return false;
 255         }
 256 
 257         @Override
 258         public final boolean permits(Set<CryptoPrimitive> primitives, Key key) {
 259             return true;
 260         }
 261 
 262         @Override
 263         public final boolean permits(Set<CryptoPrimitive> primitives,
 264                 String algorithm, Key key, AlgorithmParameters parameters) {
 265 
 266             if (algorithm == null || algorithm.length() == 0) {
 267                 throw new IllegalArgumentException(
 268                         "No algorithm name specified");
 269             }
 270 
 271             return permits(primitives, algorithm, parameters);
 272         }
 273     }
 274 }