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
26package sun.security.ssl;
27
28import java.security.AlgorithmConstraints;
29import java.security.CryptoPrimitive;
30import java.security.AlgorithmParameters;
31
32import javax.net.ssl.*;
33
34import java.security.Key;
35
36import java.util.Set;
37
38import sun.security.util.DisabledAlgorithmConstraints;
39import static sun.security.util.DisabledAlgorithmConstraints.*;
40import 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 */
48final 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}
275