1 /*
   2  * Copyright (c) 2010, 2018, 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.AlgorithmParameters;
  30 import java.security.CryptoPrimitive;
  31 import java.security.Key;
  32 import java.util.Set;
  33 import javax.net.ssl.*;
  34 import sun.security.util.DisabledAlgorithmConstraints;
  35 import static sun.security.util.DisabledAlgorithmConstraints.*;
  36 
  37 /**
  38  * Algorithm constraints for disabled algorithms property
  39  *
  40  * See the "jdk.certpath.disabledAlgorithms" specification in java.security
  41  * for the syntax of the disabled algorithm string.
  42  */
  43 final class SSLAlgorithmConstraints implements AlgorithmConstraints {
  44 
  45     private static final AlgorithmConstraints tlsDisabledAlgConstraints =
  46             new DisabledAlgorithmConstraints(PROPERTY_TLS_DISABLED_ALGS,
  47                     new SSLAlgorithmDecomposer());
  48 
  49     private static final AlgorithmConstraints x509DisabledAlgConstraints =
  50             new DisabledAlgorithmConstraints(PROPERTY_CERTPATH_DISABLED_ALGS,
  51                     new SSLAlgorithmDecomposer(true));
  52 
  53     private final AlgorithmConstraints userSpecifiedConstraints;
  54     private final AlgorithmConstraints peerSpecifiedConstraints;
  55 
  56     private final boolean enabledX509DisabledAlgConstraints;
  57 
  58     // the default algorithm constraints
  59     static final AlgorithmConstraints DEFAULT =
  60                         new SSLAlgorithmConstraints(null);
  61 
  62     // the default SSL only algorithm constraints
  63     static final AlgorithmConstraints DEFAULT_SSL_ONLY =
  64                         new SSLAlgorithmConstraints((SSLSocket)null, false);
  65 
  66     SSLAlgorithmConstraints(AlgorithmConstraints userSpecifiedConstraints) {
  67         this.userSpecifiedConstraints = userSpecifiedConstraints;
  68         this.peerSpecifiedConstraints = null;
  69         this.enabledX509DisabledAlgConstraints = true;
  70     }
  71 
  72     SSLAlgorithmConstraints(SSLSocket socket,
  73             boolean withDefaultCertPathConstraints) {
  74         AlgorithmConstraints configuredConstraints = null;
  75         if (socket != null) {
  76             HandshakeContext hc =
  77                     ((SSLSocketImpl)socket).conContext.handshakeContext;
  78             if (hc != null) {
  79                 configuredConstraints = hc.sslConfig.algorithmConstraints;
  80             } else {
  81                 configuredConstraints = null;
  82             }
  83         }
  84         this.userSpecifiedConstraints = configuredConstraints;
  85         this.peerSpecifiedConstraints = null;
  86         this.enabledX509DisabledAlgConstraints = withDefaultCertPathConstraints;
  87     }
  88 
  89     SSLAlgorithmConstraints(SSLEngine engine,
  90             boolean withDefaultCertPathConstraints) {
  91         AlgorithmConstraints configuredConstraints = null;
  92         if (engine != null) {
  93             HandshakeContext hc =
  94                     ((SSLEngineImpl)engine).conContext.handshakeContext;
  95             if (hc != null) {
  96                 configuredConstraints = hc.sslConfig.algorithmConstraints;
  97             } else {
  98                 configuredConstraints = null;
  99             }
 100         }
 101         this.userSpecifiedConstraints = configuredConstraints;
 102         this.peerSpecifiedConstraints = null;
 103         this.enabledX509DisabledAlgConstraints = withDefaultCertPathConstraints;
 104     }
 105 
 106     SSLAlgorithmConstraints(SSLSocket socket, String[] supportedAlgorithms,
 107             boolean withDefaultCertPathConstraints) {
 108         AlgorithmConstraints configuredConstraints = null;
 109         AlgorithmConstraints negotiatedConstraints = null;
 110         if (socket != null) {
 111             HandshakeContext hc =
 112                     ((SSLSocketImpl)socket).conContext.handshakeContext;
 113             if (hc != null) {
 114                 configuredConstraints = hc.sslConfig.algorithmConstraints;
 115             } else {
 116                 configuredConstraints = null;
 117             }
 118 
 119             negotiatedConstraints =
 120                 new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
 121         }
 122         this.userSpecifiedConstraints = configuredConstraints;
 123         this.peerSpecifiedConstraints = negotiatedConstraints;
 124         this.enabledX509DisabledAlgConstraints = withDefaultCertPathConstraints;
 125     }
 126 
 127     SSLAlgorithmConstraints(SSLEngine engine, String[] supportedAlgorithms,
 128             boolean withDefaultCertPathConstraints) {
 129         AlgorithmConstraints configuredConstraints = null;
 130         AlgorithmConstraints negotiatedConstraints = null;
 131         if (engine != null) {
 132             HandshakeContext hc =
 133                     ((SSLEngineImpl)engine).conContext.handshakeContext;
 134             if (hc != null) {
 135                 configuredConstraints = hc.sslConfig.algorithmConstraints;
 136             } else {
 137                 configuredConstraints = null;
 138             }
 139 
 140             negotiatedConstraints =
 141                 new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
 142         }
 143         this.userSpecifiedConstraints = configuredConstraints;
 144         this.peerSpecifiedConstraints = negotiatedConstraints;
 145         this.enabledX509DisabledAlgConstraints = withDefaultCertPathConstraints;
 146     }
 147 
 148     @Override
 149     public boolean permits(Set<CryptoPrimitive> primitives,
 150             String algorithm, AlgorithmParameters parameters) {
 151 
 152         boolean permitted = true;
 153 
 154         if (peerSpecifiedConstraints != null) {
 155             permitted = peerSpecifiedConstraints.permits(
 156                                     primitives, algorithm, parameters);
 157         }
 158 
 159         if (permitted && userSpecifiedConstraints != null) {
 160             permitted = userSpecifiedConstraints.permits(
 161                                     primitives, algorithm, parameters);
 162         }
 163 
 164         if (permitted) {
 165             permitted = tlsDisabledAlgConstraints.permits(
 166                                     primitives, algorithm, parameters);
 167         }
 168 
 169         if (permitted && enabledX509DisabledAlgConstraints) {
 170             permitted = x509DisabledAlgConstraints.permits(
 171                                     primitives, algorithm, parameters);
 172         }
 173 
 174         return permitted;
 175     }
 176 
 177     @Override
 178     public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
 179 
 180         boolean permitted = true;
 181 
 182         if (peerSpecifiedConstraints != null) {
 183             permitted = peerSpecifiedConstraints.permits(primitives, key);
 184         }
 185 
 186         if (permitted && userSpecifiedConstraints != null) {
 187             permitted = userSpecifiedConstraints.permits(primitives, key);
 188         }
 189 
 190         if (permitted) {
 191             permitted = tlsDisabledAlgConstraints.permits(primitives, key);
 192         }
 193 
 194         if (permitted && enabledX509DisabledAlgConstraints) {
 195             permitted = x509DisabledAlgConstraints.permits(primitives, key);
 196         }
 197 
 198         return permitted;
 199     }
 200 
 201     @Override
 202     public boolean permits(Set<CryptoPrimitive> primitives,
 203             String algorithm, Key key, AlgorithmParameters parameters) {
 204 
 205         boolean permitted = true;
 206 
 207         if (peerSpecifiedConstraints != null) {
 208             permitted = peerSpecifiedConstraints.permits(
 209                                     primitives, algorithm, key, parameters);
 210         }
 211 
 212         if (permitted && userSpecifiedConstraints != null) {
 213             permitted = userSpecifiedConstraints.permits(
 214                                     primitives, algorithm, key, parameters);
 215         }
 216 
 217         if (permitted) {
 218             permitted = tlsDisabledAlgConstraints.permits(
 219                                     primitives, algorithm, key, parameters);
 220         }
 221 
 222         if (permitted && enabledX509DisabledAlgConstraints) {
 223             permitted = x509DisabledAlgConstraints.permits(
 224                                     primitives, algorithm, key, parameters);
 225         }
 226 
 227         return permitted;
 228     }
 229 
 230 
 231     private static class SupportedSignatureAlgorithmConstraints
 232                                     implements AlgorithmConstraints {
 233         // supported signature algorithms
 234         private String[] supportedAlgorithms;
 235 
 236         SupportedSignatureAlgorithmConstraints(String[] supportedAlgorithms) {
 237             if (supportedAlgorithms != null) {
 238                 this.supportedAlgorithms = supportedAlgorithms.clone();
 239             } else {
 240                 this.supportedAlgorithms = null;
 241             }
 242         }
 243 
 244         @Override
 245         public boolean permits(Set<CryptoPrimitive> primitives,
 246                 String algorithm, AlgorithmParameters parameters) {
 247 
 248             if (algorithm == null || algorithm.length() == 0) {
 249                 throw new IllegalArgumentException(
 250                         "No algorithm name specified");
 251             }
 252 
 253             if (primitives == null || primitives.isEmpty()) {
 254                 throw new IllegalArgumentException(
 255                         "No cryptographic primitive specified");
 256             }
 257 
 258             if (supportedAlgorithms == null ||
 259                         supportedAlgorithms.length == 0) {
 260                 return false;
 261             }
 262 
 263             // trim the MGF part: <digest>with<encryption>and<mgf>
 264             int position = algorithm.indexOf("and");
 265             if (position > 0) {
 266                 algorithm = algorithm.substring(0, position);
 267             }
 268 
 269             for (String supportedAlgorithm : supportedAlgorithms) {
 270                 if (algorithm.equalsIgnoreCase(supportedAlgorithm)) {
 271                     return true;
 272                 }
 273             }
 274 
 275             return false;
 276         }
 277 
 278         @Override
 279         public final boolean permits(Set<CryptoPrimitive> primitives, Key key) {
 280             return true;
 281         }
 282 
 283         @Override
 284         public final boolean permits(Set<CryptoPrimitive> primitives,
 285                 String algorithm, Key key, AlgorithmParameters parameters) {
 286 
 287             if (algorithm == null || algorithm.length() == 0) {
 288                 throw new IllegalArgumentException(
 289                         "No algorithm name specified");
 290             }
 291 
 292             return permits(primitives, algorithm, parameters);
 293         }
 294     }
 295 }