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 
SSLAlgorithmConstraints(AlgorithmConstraints userSpecifiedConstraints)66     SSLAlgorithmConstraints(AlgorithmConstraints userSpecifiedConstraints) {
67         this.userSpecifiedConstraints = userSpecifiedConstraints;
68         this.peerSpecifiedConstraints = null;
69         this.enabledX509DisabledAlgConstraints = true;
70     }
71 
SSLAlgorithmConstraints(SSLSocket socket, boolean withDefaultCertPathConstraints)72     SSLAlgorithmConstraints(SSLSocket socket,
73             boolean withDefaultCertPathConstraints) {
74         this.userSpecifiedConstraints = getUserSpecifiedConstraints(socket);
75         this.peerSpecifiedConstraints = null;
76         this.enabledX509DisabledAlgConstraints = withDefaultCertPathConstraints;
77     }
78 
SSLAlgorithmConstraints(SSLEngine engine, boolean withDefaultCertPathConstraints)79     SSLAlgorithmConstraints(SSLEngine engine,
80             boolean withDefaultCertPathConstraints) {
81         this.userSpecifiedConstraints = getUserSpecifiedConstraints(engine);
82         this.peerSpecifiedConstraints = null;
83         this.enabledX509DisabledAlgConstraints = withDefaultCertPathConstraints;
84     }
85 
SSLAlgorithmConstraints(SSLSocket socket, String[] supportedAlgorithms, boolean withDefaultCertPathConstraints)86     SSLAlgorithmConstraints(SSLSocket socket, String[] supportedAlgorithms,
87             boolean withDefaultCertPathConstraints) {
88         this.userSpecifiedConstraints = getUserSpecifiedConstraints(socket);
89         this.peerSpecifiedConstraints =
90                 new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
91         this.enabledX509DisabledAlgConstraints = withDefaultCertPathConstraints;
92     }
93 
SSLAlgorithmConstraints(SSLEngine engine, String[] supportedAlgorithms, boolean withDefaultCertPathConstraints)94     SSLAlgorithmConstraints(SSLEngine engine, String[] supportedAlgorithms,
95             boolean withDefaultCertPathConstraints) {
96         this.userSpecifiedConstraints = getUserSpecifiedConstraints(engine);
97         this.peerSpecifiedConstraints =
98                 new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
99         this.enabledX509DisabledAlgConstraints = withDefaultCertPathConstraints;
100     }
101 
getUserSpecifiedConstraints( SSLEngine engine)102     private static AlgorithmConstraints getUserSpecifiedConstraints(
103             SSLEngine engine) {
104         if (engine != null) {
105             // Note that the KeyManager or TrustManager implementation may be
106             // not implemented in the same provider as SSLSocket/SSLEngine.
107             // Please check the instance before casting to use SSLEngineImpl.
108             if (engine instanceof SSLEngineImpl) {
109                 HandshakeContext hc =
110                         ((SSLEngineImpl)engine).conContext.handshakeContext;
111                 if (hc != null) {
112                     return hc.sslConfig.userSpecifiedAlgorithmConstraints;
113                 }
114             }
115 
116             return engine.getSSLParameters().getAlgorithmConstraints();
117         }
118 
119         return null;
120     }
121 
getUserSpecifiedConstraints( SSLSocket socket)122     private static AlgorithmConstraints getUserSpecifiedConstraints(
123             SSLSocket socket) {
124         if (socket != null) {
125             // Note that the KeyManager or TrustManager implementation may be
126             // not implemented in the same provider as SSLSocket/SSLEngine.
127             // Please check the instance before casting to use SSLSocketImpl.
128             if (socket instanceof SSLSocketImpl) {
129                 HandshakeContext hc =
130                         ((SSLSocketImpl)socket).conContext.handshakeContext;
131                 if (hc != null) {
132                     return hc.sslConfig.userSpecifiedAlgorithmConstraints;
133                 }
134             }
135 
136             return socket.getSSLParameters().getAlgorithmConstraints();
137         }
138 
139         return null;
140     }
141 
142     @Override
permits(Set<CryptoPrimitive> primitives, String algorithm, AlgorithmParameters parameters)143     public boolean permits(Set<CryptoPrimitive> primitives,
144             String algorithm, AlgorithmParameters parameters) {
145 
146         boolean permitted = true;
147 
148         if (peerSpecifiedConstraints != null) {
149             permitted = peerSpecifiedConstraints.permits(
150                                     primitives, algorithm, parameters);
151         }
152 
153         if (permitted && userSpecifiedConstraints != null) {
154             permitted = userSpecifiedConstraints.permits(
155                                     primitives, algorithm, parameters);
156         }
157 
158         if (permitted) {
159             permitted = tlsDisabledAlgConstraints.permits(
160                                     primitives, algorithm, parameters);
161         }
162 
163         if (permitted && enabledX509DisabledAlgConstraints) {
164             permitted = x509DisabledAlgConstraints.permits(
165                                     primitives, algorithm, parameters);
166         }
167 
168         return permitted;
169     }
170 
171     @Override
permits(Set<CryptoPrimitive> primitives, Key key)172     public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
173 
174         boolean permitted = true;
175 
176         if (peerSpecifiedConstraints != null) {
177             permitted = peerSpecifiedConstraints.permits(primitives, key);
178         }
179 
180         if (permitted && userSpecifiedConstraints != null) {
181             permitted = userSpecifiedConstraints.permits(primitives, key);
182         }
183 
184         if (permitted) {
185             permitted = tlsDisabledAlgConstraints.permits(primitives, key);
186         }
187 
188         if (permitted && enabledX509DisabledAlgConstraints) {
189             permitted = x509DisabledAlgConstraints.permits(primitives, key);
190         }
191 
192         return permitted;
193     }
194 
195     @Override
permits(Set<CryptoPrimitive> primitives, String algorithm, Key key, AlgorithmParameters parameters)196     public boolean permits(Set<CryptoPrimitive> primitives,
197             String algorithm, Key key, AlgorithmParameters parameters) {
198 
199         boolean permitted = true;
200 
201         if (peerSpecifiedConstraints != null) {
202             permitted = peerSpecifiedConstraints.permits(
203                                     primitives, algorithm, key, parameters);
204         }
205 
206         if (permitted && userSpecifiedConstraints != null) {
207             permitted = userSpecifiedConstraints.permits(
208                                     primitives, algorithm, key, parameters);
209         }
210 
211         if (permitted) {
212             permitted = tlsDisabledAlgConstraints.permits(
213                                     primitives, algorithm, key, parameters);
214         }
215 
216         if (permitted && enabledX509DisabledAlgConstraints) {
217             permitted = x509DisabledAlgConstraints.permits(
218                                     primitives, algorithm, key, parameters);
219         }
220 
221         return permitted;
222     }
223 
224 
225     private static class SupportedSignatureAlgorithmConstraints
226                                     implements AlgorithmConstraints {
227         // supported signature algorithms
228         private String[] supportedAlgorithms;
229 
SupportedSignatureAlgorithmConstraints(String[] supportedAlgorithms)230         SupportedSignatureAlgorithmConstraints(String[] supportedAlgorithms) {
231             if (supportedAlgorithms != null) {
232                 this.supportedAlgorithms = supportedAlgorithms.clone();
233             } else {
234                 this.supportedAlgorithms = null;
235             }
236         }
237 
238         @Override
permits(Set<CryptoPrimitive> primitives, String algorithm, AlgorithmParameters parameters)239         public boolean permits(Set<CryptoPrimitive> primitives,
240                 String algorithm, AlgorithmParameters parameters) {
241 
242             if (algorithm == null || algorithm.isEmpty()) {
243                 throw new IllegalArgumentException(
244                         "No algorithm name specified");
245             }
246 
247             if (primitives == null || primitives.isEmpty()) {
248                 throw new IllegalArgumentException(
249                         "No cryptographic primitive specified");
250             }
251 
252             if (supportedAlgorithms == null ||
253                         supportedAlgorithms.length == 0) {
254                 return false;
255             }
256 
257             // trim the MGF part: <digest>with<encryption>and<mgf>
258             int position = algorithm.indexOf("and");
259             if (position > 0) {
260                 algorithm = algorithm.substring(0, position);
261             }
262 
263             for (String supportedAlgorithm : supportedAlgorithms) {
264                 if (algorithm.equalsIgnoreCase(supportedAlgorithm)) {
265                     return true;
266                 }
267             }
268 
269             return false;
270         }
271 
272         @Override
permits(Set<CryptoPrimitive> primitives, Key key)273         public final boolean permits(Set<CryptoPrimitive> primitives, Key key) {
274             return true;
275         }
276 
277         @Override
permits(Set<CryptoPrimitive> primitives, String algorithm, Key key, AlgorithmParameters parameters)278         public final boolean permits(Set<CryptoPrimitive> primitives,
279                 String algorithm, Key key, AlgorithmParameters parameters) {
280 
281             if (algorithm == null || algorithm.isEmpty()) {
282                 throw new IllegalArgumentException(
283                         "No algorithm name specified");
284             }
285 
286             return permits(primitives, algorithm, parameters);
287         }
288     }
289 }
290