1 /*
  2  * Copyright (c) 2018, 2022, 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.PrivateKey;
 29 import java.security.PublicKey;
 30 import java.security.cert.X509Certificate;
 31 import java.security.interfaces.ECKey;
 32 import java.security.interfaces.ECPublicKey;
 33 import java.security.interfaces.XECKey;
 34 import java.security.spec.AlgorithmParameterSpec;
 35 import java.security.spec.ECParameterSpec;
 36 import java.security.spec.NamedParameterSpec;
 37 import java.util.AbstractMap.SimpleImmutableEntry;
 38 import java.util.Arrays;
 39 import java.util.Map;
 40 import javax.net.ssl.X509ExtendedKeyManager;
 41 
 42 enum X509Authentication implements SSLAuthentication {
 43     // Require rsaEncryption public key
 44     RSA         ("RSA",         "RSA"),
 45 
 46     // Require RSASSA-PSS public key
 47     RSASSA_PSS  ("RSASSA-PSS",  "RSASSA-PSS"),
 48 
 49     // Require rsaEncryption or RSASSA-PSS public key
 50     //
 51     // Note that this is a specific scheme for TLS 1.2. (EC)DHE_RSA cipher
 52     // suites of TLS 1.2 can use either rsaEncryption or RSASSA-PSS public
 53     // key for authentication and handshake.
 54     RSA_OR_PSS  ("RSA_OR_PSS",  "RSA", "RSASSA-PSS"),
 55 
 56     // Require DSA public key
 57     DSA         ("DSA",         "DSA"),
 58 
 59     // Require EC public key
 60     EC          ("EC",          "EC"),
 61     // Edwards-Curve key
 62     EDDSA       ("EdDSA",       "EdDSA");
 63 
 64     final String keyAlgorithm;
 65     final String[] keyTypes;
 66 
 67     X509Authentication(String keyAlgorithm,
 68                        String... keyTypes) {
 69         this.keyAlgorithm = keyAlgorithm;
 70         this.keyTypes = keyTypes;
 71     }
 72 
 73     static X509Authentication valueOfKeyAlgorithm(String keyAlgorithm) {
 74         for (X509Authentication au : X509Authentication.values()) {
 75             if (au.keyAlgorithm.equals(keyAlgorithm)) {
 76                 return au;
 77             }
 78         }
 79 
 80         return null;
 81     }
 82 
 83     @Override
 84     public SSLPossession createPossession(HandshakeContext handshakeContext) {
 85         return X509Authentication.createPossession(handshakeContext, keyTypes);
 86     }
 87 
 88     @Override
 89     public SSLHandshake[] getRelatedHandshakers(
 90             HandshakeContext handshakeContext) {
 91         if (!handshakeContext.negotiatedProtocol.useTLS13PlusSpec()) {
 92             return new SSLHandshake[] {
 93                     SSLHandshake.CERTIFICATE,
 94                     SSLHandshake.CERTIFICATE_REQUEST
 95                 };
 96         }   // Otherwise, TLS 1.3 does not use this method.
 97 
 98         return new SSLHandshake[0];
 99     }
100 
101     @SuppressWarnings({"unchecked", "rawtypes"})
102     @Override
103     public Map.Entry<Byte, HandshakeProducer>[] getHandshakeProducers(
104             HandshakeContext handshakeContext) {
105         if (!handshakeContext.negotiatedProtocol.useTLS13PlusSpec()) {
106             return (Map.Entry<Byte, HandshakeProducer>[])(new Map.Entry[] {
107                     new SimpleImmutableEntry<Byte, HandshakeProducer>(
108                         SSLHandshake.CERTIFICATE.id,
109                         SSLHandshake.CERTIFICATE
110                     )
111                 });
112         }   // Otherwise, TLS 1.3 does not use this method.
113 
114         return (Map.Entry<Byte, HandshakeProducer>[])(new Map.Entry[0]);
115     }
116 
117     static final class X509Possession implements SSLPossession {
118         // Proof of possession of the private key corresponding to the public
119         // key for which a certificate is being provided for authentication.
120         final X509Certificate[]   popCerts;
121         final PrivateKey          popPrivateKey;
122 
123         X509Possession(PrivateKey popPrivateKey,
124                 X509Certificate[] popCerts) {
125             this.popCerts = popCerts;
126             this.popPrivateKey = popPrivateKey;
127         }
128 
129         ECParameterSpec getECParameterSpec() {
130             if (popPrivateKey == null ||
131                     !"EC".equals(popPrivateKey.getAlgorithm())) {
132                 return null;
133             }
134 
135             if (popPrivateKey instanceof ECKey) {
136                 return ((ECKey)popPrivateKey).getParams();
137             } else if (popCerts != null && popCerts.length != 0) {
138                 // The private key not extractable, get the parameters from
139                 // the X.509 certificate.
140                 PublicKey publicKey = popCerts[0].getPublicKey();
141                 if (publicKey instanceof ECKey) {
142                     return ((ECKey)publicKey).getParams();
143                 }
144             }
145 
146             return null;
147         }
148 
149         // Similar to above, but for XEC.
150         NamedParameterSpec getXECParameterSpec() {
151             if (popPrivateKey == null ||
152                     !"XEC".equals(popPrivateKey.getAlgorithm())) {
153                 return null;
154             }
155 
156             if (popPrivateKey instanceof XECKey) {
157                 AlgorithmParameterSpec params =
158                         ((XECKey)popPrivateKey).getParams();
159                 if (params instanceof NamedParameterSpec){
160                     return (NamedParameterSpec)params;
161                 }
162             } else if (popCerts != null && popCerts.length != 0) {
163                 // The private key not extractable, get the parameters from
164                 // the X.509 certificate.
165                 PublicKey publicKey = popCerts[0].getPublicKey();
166                 if (publicKey instanceof XECKey) {
167                     AlgorithmParameterSpec params =
168                             ((XECKey)publicKey).getParams();
169                     if (params instanceof NamedParameterSpec){
170                         return (NamedParameterSpec)params;
171                     }
172                 }
173             }
174 
175             return null;
176         }
177     }
178 
179     static final class X509Credentials implements SSLCredentials {
180         final X509Certificate[]   popCerts;
181         final PublicKey           popPublicKey;
182 
183         X509Credentials(PublicKey popPublicKey, X509Certificate[] popCerts) {
184             this.popCerts = popCerts;
185             this.popPublicKey = popPublicKey;
186         }
187     }
188 
189     public static SSLPossession createPossession(
190             HandshakeContext context, String[] keyTypes) {
191         if (context.sslConfig.isClientMode) {
192             return createClientPossession(
193                     (ClientHandshakeContext) context, keyTypes);
194         } else {
195             return createServerPossession(
196                     (ServerHandshakeContext) context, keyTypes);
197         }
198     }
199 
200     // Used by TLS 1.2 and TLS 1.3.
201     private static SSLPossession createClientPossession(
202             ClientHandshakeContext chc, String[] keyTypes) {
203         X509ExtendedKeyManager km = chc.sslContext.getX509KeyManager();
204         String clientAlias = null;
205         if (chc.conContext.transport instanceof SSLSocketImpl socket) {
206             clientAlias = km.chooseClientAlias(
207                     keyTypes,
208                     chc.peerSupportedAuthorities == null ? null :
209                             chc.peerSupportedAuthorities.clone(),
210                     socket);
211         } else if (chc.conContext.transport instanceof SSLEngineImpl engine) {
212             clientAlias = km.chooseEngineClientAlias(
213                     keyTypes,
214                     chc.peerSupportedAuthorities == null ? null :
215                             chc.peerSupportedAuthorities.clone(),
216                     engine);
217         }
218 
219         if (clientAlias == null) {
220             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
221                 SSLLogger.finest("No X.509 cert selected for "
222                         + Arrays.toString(keyTypes));
223             }
224             return null;
225         }
226 
227         PrivateKey clientPrivateKey = km.getPrivateKey(clientAlias);
228         if (clientPrivateKey == null) {
229             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
230                 SSLLogger.finest(
231                         clientAlias + " is not a private key entry");
232             }
233             return null;
234         }
235 
236         X509Certificate[] clientCerts = km.getCertificateChain(clientAlias);
237         if ((clientCerts == null) || (clientCerts.length == 0)) {
238             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
239                 SSLLogger.finest(clientAlias +
240                         " is a private key entry with no cert chain stored");
241             }
242             return null;
243         }
244 
245         String privateKeyAlgorithm = clientPrivateKey.getAlgorithm();
246         if (!Arrays.asList(keyTypes).contains(privateKeyAlgorithm)) {
247             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
248                 SSLLogger.fine(
249                         clientAlias + " private key algorithm " +
250                                 privateKeyAlgorithm + " not in request list");
251             }
252             return null;
253         }
254 
255         String publicKeyAlgorithm = clientCerts[0].getPublicKey().getAlgorithm();
256         if (!privateKeyAlgorithm.equals(publicKeyAlgorithm)) {
257             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
258                 SSLLogger.fine(
259                         clientAlias + " private or public key is not of " +
260                                 "same algorithm: " +
261                                 privateKeyAlgorithm + " vs " +
262                                 publicKeyAlgorithm);
263             }
264             return null;
265         }
266 
267         return new X509Possession(clientPrivateKey, clientCerts);
268     }
269 
270     private static SSLPossession createServerPossession(
271             ServerHandshakeContext shc, String[] keyTypes) {
272         X509ExtendedKeyManager km = shc.sslContext.getX509KeyManager();
273         String serverAlias = null;
274         for (String keyType : keyTypes) {
275             if (shc.conContext.transport instanceof SSLSocketImpl socket) {
276                 serverAlias = km.chooseServerAlias(keyType,
277                         shc.peerSupportedAuthorities == null ? null :
278                                 shc.peerSupportedAuthorities.clone(),
279                         socket);
280             } else if (shc.conContext.transport instanceof SSLEngineImpl engine) {
281                 serverAlias = km.chooseEngineServerAlias(keyType,
282                         shc.peerSupportedAuthorities == null ? null :
283                                 shc.peerSupportedAuthorities.clone(),
284                         engine);
285             }
286 
287             if (serverAlias == null) {
288                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
289                     SSLLogger.finest("No X.509 cert selected for " + keyType);
290                 }
291                 continue;
292             }
293 
294             PrivateKey serverPrivateKey = km.getPrivateKey(serverAlias);
295             if (serverPrivateKey == null) {
296                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
297                     SSLLogger.finest(
298                             serverAlias + " is not a private key entry");
299                 }
300                 continue;
301             }
302 
303             X509Certificate[] serverCerts = km.getCertificateChain(serverAlias);
304             if ((serverCerts == null) || (serverCerts.length == 0)) {
305                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
306                     SSLLogger.finest(
307                             serverAlias + " is not a certificate entry");
308                 }
309                 continue;
310             }
311 
312             PublicKey serverPublicKey = serverCerts[0].getPublicKey();
313             if ((!serverPrivateKey.getAlgorithm().equals(keyType))
314                     || (!serverPublicKey.getAlgorithm().equals(keyType))) {
315                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
316                     SSLLogger.fine(
317                             serverAlias + " private or public key is not of " +
318                                     keyType + " algorithm");
319                 }
320                 continue;
321             }
322 
323             // For TLS 1.2 and prior versions, the public key of an EC cert
324             // MUST use a curve and point format supported by the client.
325             // But for TLS 1.3, signature algorithms are negotiated
326             // independently via the "signature_algorithms" extension.
327             if (!shc.negotiatedProtocol.useTLS13PlusSpec() &&
328                     keyType.equals("EC")) {
329                 if (!(serverPublicKey instanceof ECPublicKey)) {
330                     if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
331                         SSLLogger.warning(serverAlias +
332                                 " public key is not an instance of ECPublicKey");
333                     }
334                     continue;
335                 }
336 
337                 // For ECC certs, check whether we support the EC domain
338                 // parameters.  If the client sent a supported_groups
339                 // ClientHello extension, check against that too for
340                 // TLS 1.2 and prior versions.
341                 ECParameterSpec params =
342                         ((ECPublicKey) serverPublicKey).getParams();
343                 NamedGroup namedGroup = NamedGroup.valueOf(params);
344                 if ((namedGroup == null) ||
345                         (!NamedGroup.isEnabled(shc.sslConfig, namedGroup)) ||
346                         ((shc.clientRequestedNamedGroups != null) &&
347                                 !shc.clientRequestedNamedGroups.contains(namedGroup))) {
348 
349                     if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
350                         SSLLogger.warning(
351                                 "Unsupported named group (" + namedGroup +
352                                         ") used in the " + serverAlias + " certificate");
353                     }
354 
355                     continue;
356                 }
357             }
358 
359             return new X509Possession(serverPrivateKey, serverCerts);
360         }
361         return null;
362     }
363 }