1 package org.bouncycastle.jsse.provider;
2 
3 import java.io.IOException;
4 import java.security.Key;
5 import java.security.PrivateKey;
6 import java.security.PublicKey;
7 import java.security.cert.X509Certificate;
8 import java.util.ArrayList;
9 import java.util.Collection;
10 import java.util.Collections;
11 import java.util.EnumSet;
12 import java.util.Enumeration;
13 import java.util.HashSet;
14 import java.util.Hashtable;
15 import java.util.LinkedHashSet;
16 import java.util.List;
17 import java.util.Set;
18 import java.util.Vector;
19 
20 import javax.security.auth.x500.X500Principal;
21 
22 import org.bouncycastle.asn1.ASN1Encodable;
23 import org.bouncycastle.asn1.ASN1Encoding;
24 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
25 import org.bouncycastle.asn1.ASN1Primitive;
26 import org.bouncycastle.asn1.ocsp.OCSPResponse;
27 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
28 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
29 import org.bouncycastle.asn1.x500.X500Name;
30 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
31 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
32 import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
33 import org.bouncycastle.jsse.BCSNIHostName;
34 import org.bouncycastle.jsse.BCSNIMatcher;
35 import org.bouncycastle.jsse.BCSNIServerName;
36 import org.bouncycastle.jsse.BCStandardConstants;
37 import org.bouncycastle.jsse.BCX509ExtendedTrustManager;
38 import org.bouncycastle.jsse.BCX509Key;
39 import org.bouncycastle.jsse.java.security.BCCryptoPrimitive;
40 import org.bouncycastle.tls.AlertDescription;
41 import org.bouncycastle.tls.AlertLevel;
42 import org.bouncycastle.tls.Certificate;
43 import org.bouncycastle.tls.CertificateEntry;
44 import org.bouncycastle.tls.CertificateStatus;
45 import org.bouncycastle.tls.CertificateStatusType;
46 import org.bouncycastle.tls.ClientCertificateType;
47 import org.bouncycastle.tls.IdentifierType;
48 import org.bouncycastle.tls.KeyExchangeAlgorithm;
49 import org.bouncycastle.tls.NamedGroup;
50 import org.bouncycastle.tls.ProtocolName;
51 import org.bouncycastle.tls.ProtocolVersion;
52 import org.bouncycastle.tls.SecurityParameters;
53 import org.bouncycastle.tls.ServerName;
54 import org.bouncycastle.tls.SignatureAlgorithm;
55 import org.bouncycastle.tls.SignatureAndHashAlgorithm;
56 import org.bouncycastle.tls.TlsContext;
57 import org.bouncycastle.tls.TlsCredentialedDecryptor;
58 import org.bouncycastle.tls.TlsCredentialedSigner;
59 import org.bouncycastle.tls.TlsUtils;
60 import org.bouncycastle.tls.TrustedAuthority;
61 import org.bouncycastle.tls.crypto.TlsCertificate;
62 import org.bouncycastle.tls.crypto.TlsCryptoParameters;
63 import org.bouncycastle.tls.crypto.impl.jcajce.JcaDefaultTlsCredentialedSigner;
64 import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCertificate;
65 import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto;
66 import org.bouncycastle.tls.crypto.impl.jcajce.JceDefaultTlsCredentialedDecryptor;
67 
68 abstract class JsseUtils
69 {
70     private static final boolean provTlsAllowLegacyMasterSecret =
71         PropertyUtils.getBooleanSystemProperty("jdk.tls.allowLegacyMasterSecret", true);
72     private static final boolean provTlsAllowLegacyResumption =
73         PropertyUtils.getBooleanSystemProperty("jdk.tls.allowLegacyResumption", false);
74     private static final int provTlsMaxCertificateChainLength =
75         PropertyUtils.getIntegerSystemProperty("jdk.tls.maxCertificateChainLength", 10, 1, Integer.MAX_VALUE);
76     private static final int provTlsMaxHandshakeMessageSize =
77         PropertyUtils.getIntegerSystemProperty("jdk.tls.maxHandshakeMessageSize", 32768, 1024, Integer.MAX_VALUE);
78     private static final boolean provTlsRequireCloseNotify =
79         PropertyUtils.getBooleanSystemProperty("com.sun.net.ssl.requireCloseNotify", true);
80     private static final boolean provTlsUseExtendedMasterSecret =
81         PropertyUtils.getBooleanSystemProperty("jdk.tls.useExtendedMasterSecret", true);
82 
83     static final Set<BCCryptoPrimitive> KEY_AGREEMENT_CRYPTO_PRIMITIVES_BC =
84         Collections.unmodifiableSet(EnumSet.of(BCCryptoPrimitive.KEY_AGREEMENT));
85     static final Set<BCCryptoPrimitive> KEY_ENCAPSULATION_CRYPTO_PRIMITIVES_BC =
86         Collections.unmodifiableSet(EnumSet.of(BCCryptoPrimitive.KEY_ENCAPSULATION));
87     static final Set<BCCryptoPrimitive> SIGNATURE_CRYPTO_PRIMITIVES_BC =
88         Collections.unmodifiableSet(EnumSet.of(BCCryptoPrimitive.SIGNATURE));
89 
90     static String EMPTY_STRING = "";
91     static X509Certificate[] EMPTY_X509CERTIFICATES = new X509Certificate[0];
92 
93     static class BCUnknownServerName extends BCSNIServerName
94     {
BCUnknownServerName(int nameType, byte[] encoded)95         BCUnknownServerName(int nameType, byte[] encoded)
96         {
97             super(nameType, encoded);
98         }
99     }
100 
allowLegacyMasterSecret()101     static boolean allowLegacyMasterSecret()
102     {
103         return provTlsAllowLegacyMasterSecret;
104     }
105 
allowLegacyResumption()106     static boolean allowLegacyResumption()
107     {
108         return provTlsAllowLegacyResumption;
109     }
110 
checkSessionCreationEnabled(ProvTlsManager manager)111     static void checkSessionCreationEnabled(ProvTlsManager manager)
112     {
113         if (!manager.getEnableSessionCreation())
114         {
115             throw new IllegalStateException("Cannot resume session and session creation is disabled");
116         }
117     }
118 
clone(T[] ts)119     static <T> T[] clone(T[] ts)
120     {
121         return null == ts ? null : ts.clone();
122     }
123 
contains(String[] values, String value)124     static boolean contains(String[] values, String value)
125     {
126         for (int i = 0; i < values.length; ++i)
127         {
128             if (value.equals(values[i]))
129             {
130                 return true;
131             }
132         }
133         return false;
134     }
135 
containsNull(T[] ts)136     static <T> boolean containsNull(T[] ts)
137     {
138         for (int i = 0; i < ts.length; ++i)
139         {
140             if (null == ts[i])
141             {
142                 return true;
143             }
144         }
145         return false;
146     }
147 
copyOf(String[] data, int newLength)148     static String[] copyOf(String[] data, int newLength)
149     {
150         String[] tmp = new String[newLength];
151         System.arraycopy(data, 0, tmp, 0, Math.min(data.length, newLength));
152         return tmp;
153     }
154 
createCredentialedDecryptor(JcaTlsCrypto crypto, BCX509Key x509Key)155     static TlsCredentialedDecryptor createCredentialedDecryptor(JcaTlsCrypto crypto, BCX509Key x509Key)
156     {
157         PrivateKey privateKey = x509Key.getPrivateKey();
158         Certificate certificate = getCertificateMessage(crypto, x509Key.getCertificateChain());
159 
160         return new JceDefaultTlsCredentialedDecryptor(crypto, certificate, privateKey);
161     }
162 
createCredentialedSigner(TlsContext context, JcaTlsCrypto crypto, BCX509Key x509Key, SignatureAndHashAlgorithm sigAndHashAlg)163     static TlsCredentialedSigner createCredentialedSigner(TlsContext context, JcaTlsCrypto crypto, BCX509Key x509Key,
164         SignatureAndHashAlgorithm sigAndHashAlg)
165     {
166         /*
167          * TODO[jsse] Before proceeding with EC credentials, check (TLS 1.2+) that the used curve
168          * was actually declared in the client's elliptic_curves/named_groups extension.
169          */
170 
171         TlsCryptoParameters cryptoParams = new TlsCryptoParameters(context);
172         PrivateKey privateKey = x509Key.getPrivateKey();
173         Certificate certificate = getCertificateMessage(crypto, x509Key.getCertificateChain());
174 
175         return new JcaDefaultTlsCredentialedSigner(cryptoParams, crypto, privateKey, certificate, sigAndHashAlg);
176     }
177 
createCredentialedSigner13(TlsContext context, JcaTlsCrypto crypto, BCX509Key x509Key, SignatureAndHashAlgorithm sigAndHashAlg, byte[] certificateRequestContext)178     static TlsCredentialedSigner createCredentialedSigner13(TlsContext context, JcaTlsCrypto crypto, BCX509Key x509Key,
179         SignatureAndHashAlgorithm sigAndHashAlg, byte[] certificateRequestContext)
180     {
181         /*
182          * TODO[jsse] Before proceeding with EC credentials, check (TLS 1.2+) that the used curve
183          * was actually declared in the client's elliptic_curves/named_groups extension.
184          */
185 
186         TlsCryptoParameters cryptoParams = new TlsCryptoParameters(context);
187         PrivateKey privateKey = x509Key.getPrivateKey();
188         Certificate certificate = getCertificateMessage13(crypto, x509Key.getCertificateChain(),
189             certificateRequestContext);
190 
191         return new JcaDefaultTlsCredentialedSigner(cryptoParams, crypto, privateKey, certificate, sigAndHashAlg);
192     }
193 
equals(Object a, Object b)194     static boolean equals(Object a, Object b)
195     {
196         return a == b || (null != a && null != b && a.equals(b));
197     }
198 
getMaxCertificateChainLength()199     static int getMaxCertificateChainLength()
200     {
201         return provTlsMaxCertificateChainLength;
202     }
203 
getMaxHandshakeMessageSize()204     static int getMaxHandshakeMessageSize()
205     {
206         return provTlsMaxHandshakeMessageSize;
207     }
208 
getNamedCurveOID(PublicKey publicKey)209     static ASN1ObjectIdentifier getNamedCurveOID(PublicKey publicKey)
210     {
211         try
212         {
213             SubjectPublicKeyInfo spki = SubjectPublicKeyInfo.getInstance(publicKey.getEncoded());
214             AlgorithmIdentifier algID = spki.getAlgorithm();
215             if (X9ObjectIdentifiers.id_ecPublicKey.equals(algID.getAlgorithm()))
216             {
217                 ASN1Encodable parameters = algID.getParameters();
218                 if (null != parameters)
219                 {
220                     ASN1Primitive primitive = parameters.toASN1Primitive();
221                     if (primitive instanceof ASN1ObjectIdentifier)
222                     {
223                         return (ASN1ObjectIdentifier)primitive;
224                     }
225                 }
226             }
227         }
228         catch (Exception e)
229         {
230         }
231 
232         return null;
233     }
234 
resize(String[] data, int count)235     static String[] resize(String[] data, int count)
236     {
237         if (count < data.length)
238         {
239             data = copyOf(data, count);
240         }
241         return data;
242     }
243 
getApplicationProtocol(SecurityParameters securityParameters)244     static String getApplicationProtocol(SecurityParameters securityParameters)
245     {
246         if (null == securityParameters || !securityParameters.isApplicationProtocolSet())
247         {
248             return null;
249         }
250 
251         ProtocolName applicationProtocol = securityParameters.getApplicationProtocol();
252         if (null == applicationProtocol)
253         {
254             return "";
255         }
256 
257         return applicationProtocol.getUtf8Decoding();
258     }
259 
getAuthTypeClient(short signatureAlgorithm)260     static String getAuthTypeClient(short signatureAlgorithm)
261     {
262         /*
263          * For use with checkClientTrusted calls on a trust manager.
264          * "Determined by the actual certificate used" according to JSSE Standard Names, but in
265          * practice trust managers only require the authType to be a non-null, non-empty String.
266          */
267 
268         switch (signatureAlgorithm)
269         {
270         case SignatureAlgorithm.rsa:
271             return "RSA";
272         case SignatureAlgorithm.dsa:
273             return "DSA";
274         case SignatureAlgorithm.ecdsa:
275         case SignatureAlgorithm.ecdsa_brainpoolP256r1tls13_sha256:
276         case SignatureAlgorithm.ecdsa_brainpoolP384r1tls13_sha384:
277         case SignatureAlgorithm.ecdsa_brainpoolP512r1tls13_sha512:
278             return "EC";
279         case SignatureAlgorithm.ed25519:
280             return "Ed25519";
281         case SignatureAlgorithm.ed448:
282             return "Ed448";
283         case SignatureAlgorithm.rsa_pss_rsae_sha256:
284         case SignatureAlgorithm.rsa_pss_rsae_sha384:
285         case SignatureAlgorithm.rsa_pss_rsae_sha512:
286             return "RSA";
287         case SignatureAlgorithm.rsa_pss_pss_sha256:
288         case SignatureAlgorithm.rsa_pss_pss_sha384:
289         case SignatureAlgorithm.rsa_pss_pss_sha512:
290             return "RSASSA-PSS";
291         default:
292             throw new IllegalArgumentException();
293         }
294     }
295 
getAuthTypeServer(int keyExchangeAlgorithm)296     static String getAuthTypeServer(int keyExchangeAlgorithm)
297     {
298         /*
299          * For use with checkServerTrusted calls on a trust manager.
300          * "The key exchange algorithm portion of the cipher suites represented as a String [..]"
301          * according to JSSE Standard Names.
302          */
303 
304         switch (keyExchangeAlgorithm)
305         {
306         case KeyExchangeAlgorithm.DH_DSS:
307             return "DH_DSS";
308         case KeyExchangeAlgorithm.DH_RSA:
309             return "DH_RSA";
310         case KeyExchangeAlgorithm.DHE_DSS:
311             return "DHE_DSS";
312         case KeyExchangeAlgorithm.DHE_RSA:
313             return "DHE_RSA";
314         case KeyExchangeAlgorithm.ECDH_ECDSA:
315             return "ECDH_ECDSA";
316         case KeyExchangeAlgorithm.ECDH_RSA:
317             return "ECDH_RSA";
318         case KeyExchangeAlgorithm.ECDHE_ECDSA:
319             return "ECDHE_ECDSA";
320         case KeyExchangeAlgorithm.ECDHE_RSA:
321             return "ECDHE_RSA";
322         case KeyExchangeAlgorithm.NULL:
323             // For compatibility with SunJSSE, use "UNKNOWN" for TLS 1.3 cipher suites.
324 //            return "NULL";
325             return "UNKNOWN";
326         case KeyExchangeAlgorithm.RSA:
327             // Prefixed to disambiguate from RSA signing credentials
328             return "KE:RSA";
329         case KeyExchangeAlgorithm.SRP_DSS:
330             return "SRP_DSS";
331         case KeyExchangeAlgorithm.SRP_RSA:
332             return "SRP_RSA";
333         default:
334             throw new IllegalArgumentException();
335         }
336     }
337 
getCertificateAuthorities(BCX509ExtendedTrustManager x509TrustManager)338     static Vector<X500Name> getCertificateAuthorities(BCX509ExtendedTrustManager x509TrustManager)
339     {
340         Set<X500Principal> caSubjects = new HashSet<X500Principal>();
341         for (X509Certificate acceptedIssuer : x509TrustManager.getAcceptedIssuers())
342         {
343             if (acceptedIssuer.getBasicConstraints() >= 0)
344             {
345                 caSubjects.add(acceptedIssuer.getSubjectX500Principal());
346             }
347             else
348             {
349                 // Trusting a non-CA certificate, so include its issuer as a CA
350                 caSubjects.add(acceptedIssuer.getIssuerX500Principal());
351             }
352         }
353 
354         if (caSubjects.isEmpty())
355         {
356             return null;
357         }
358 
359         /*
360          * TODO[jsse] Destined for an extension, but what if there are too many? Extension has total
361          * size limit, and some servers may limit e.g. ClientHello total size.
362          */
363         Vector<X500Name> certificateAuthorities = new Vector<X500Name>(caSubjects.size());
364         for (X500Principal caSubject : caSubjects)
365         {
366             certificateAuthorities.add(X500Name.getInstance(caSubject.getEncoded()));
367         }
368         return certificateAuthorities;
369     }
370 
getCertificateMessage(JcaTlsCrypto crypto, X509Certificate[] chain)371     static Certificate getCertificateMessage(JcaTlsCrypto crypto, X509Certificate[] chain)
372     {
373         if (TlsUtils.isNullOrEmpty(chain))
374         {
375             throw new IllegalArgumentException();
376         }
377 
378         TlsCertificate[] certificateList = new TlsCertificate[chain.length];
379         for (int i = 0; i < chain.length; ++i)
380         {
381             certificateList[i] = new JcaTlsCertificate(crypto, chain[i]);
382         }
383         return new Certificate(certificateList);
384     }
385 
getCertificateMessage13(JcaTlsCrypto crypto, X509Certificate[] chain, byte[] certificateRequestContext)386     static Certificate getCertificateMessage13(JcaTlsCrypto crypto, X509Certificate[] chain,
387         byte[] certificateRequestContext)
388     {
389         if (TlsUtils.isNullOrEmpty(chain))
390         {
391             throw new IllegalArgumentException();
392         }
393 
394         CertificateEntry[] certificateEntryList = new CertificateEntry[chain.length];
395         for (int i = 0; i < chain.length; ++i)
396         {
397             JcaTlsCertificate certificate = new JcaTlsCertificate(crypto, chain[i]);
398 
399             // TODO[tls13] Support various extensions
400             Hashtable<Integer, byte[]> extensions = null;
401 
402             certificateEntryList[i] = new CertificateEntry(certificate, extensions);
403         }
404 
405         return new Certificate(certificateRequestContext, certificateEntryList);
406     }
407 
getEndEntity(JcaTlsCrypto crypto, Certificate certificateMessage)408     static X509Certificate getEndEntity(JcaTlsCrypto crypto, Certificate certificateMessage) throws IOException
409     {
410         if (certificateMessage == null || certificateMessage.isEmpty())
411         {
412             return null;
413         }
414 
415         return getX509Certificate(crypto, certificateMessage.getCertificateAt(0));
416     }
417 
getJcaSignatureAlgorithmBC(String jcaSignatureAlgorithm, String keyAlgorithm)418     static String getJcaSignatureAlgorithmBC(String jcaSignatureAlgorithm, String keyAlgorithm)
419     {
420         if (!jcaSignatureAlgorithm.endsWith("withRSAandMGF1"))
421         {
422             return jcaSignatureAlgorithm;
423         }
424 
425         return jcaSignatureAlgorithm + ":" + keyAlgorithm;
426     }
427 
getKeyType13(String keyAlgorithm, int namedGroup13)428     static String getKeyType13(String keyAlgorithm, int namedGroup13)
429     {
430         if (namedGroup13 < 0)
431         {
432             return keyAlgorithm;
433         }
434 
435         return keyAlgorithm + "/" + NamedGroup.getStandardName(namedGroup13);
436     }
437 
getKeyTypeLegacyClient(short clientCertificateType)438     static String getKeyTypeLegacyClient(short clientCertificateType)
439     {
440         switch (clientCertificateType)
441         {
442         /*
443          * BCJSSE doesn't support any static key exchange cipher suites; any of these values would
444          * be filtered out (as invalid) by the low-level TLS code.
445          */
446 //        case ClientCertificateType.dss_fixed_dh:
447 //            return "DH_DSA";
448 //        case ClientCertificateType.ecdsa_fixed_ecdh:
449 //            return "EC_EC";
450 //        case ClientCertificateType.rsa_fixed_dh:
451 //            return "DH_RSA";
452 //        case ClientCertificateType.rsa_fixed_ecdh:
453 //            return "EC_RSA";
454 
455         case ClientCertificateType.dss_sign:
456             return "DSA";
457         case ClientCertificateType.ecdsa_sign:
458             return "EC";
459         case ClientCertificateType.rsa_sign:
460             return "RSA";
461         default:
462             throw new IllegalArgumentException();
463         }
464     }
465 
getKeyTypeLegacyServer(int keyExchangeAlgorithm)466     static String getKeyTypeLegacyServer(int keyExchangeAlgorithm)
467     {
468         /*
469          * For use with chooseServerAlias calls on a key manager. JSSE Standard Names suggest using
470          * the same set of key types as getKeyTypeClient, but this doesn't give enough information
471          * to the key manager, so we currently use the same names as getAuthTypeServer.
472          */
473 
474         return getAuthTypeServer(keyExchangeAlgorithm);
475     }
476 
getProtocolNames(String[] applicationProtocols)477     static Vector<ProtocolName> getProtocolNames(String[] applicationProtocols)
478     {
479         if (TlsUtils.isNullOrEmpty(applicationProtocols))
480         {
481             return null;
482         }
483 
484         Vector<ProtocolName> result = new Vector<ProtocolName>(applicationProtocols.length);
485         for (String applicationProtocol : applicationProtocols)
486         {
487             result.add(ProtocolName.asUtf8Encoding(applicationProtocol));
488         }
489         return result;
490     }
491 
getProtocolNames(Vector<ProtocolName> applicationProtocols)492     static List<String> getProtocolNames(Vector<ProtocolName> applicationProtocols)
493     {
494         if (null == applicationProtocols || applicationProtocols.isEmpty())
495         {
496             return null;
497         }
498 
499         ArrayList<String> result = new ArrayList<String>(applicationProtocols.size());
500         for (ProtocolName applicationProtocol : applicationProtocols)
501         {
502             result.add(applicationProtocol.getUtf8Decoding());
503         }
504         return result;
505     }
506 
getStatusResponse(OCSPResponse ocspResponse)507     static byte[] getStatusResponse(OCSPResponse ocspResponse) throws IOException
508     {
509         return null == ocspResponse ? TlsUtils.EMPTY_BYTES : ocspResponse.getEncoded(ASN1Encoding.DER);
510     }
511 
getStatusResponses(CertificateStatus certificateStatus)512     static List<byte[]> getStatusResponses(CertificateStatus certificateStatus) throws IOException
513     {
514         if (null != certificateStatus)
515         {
516             switch (certificateStatus.getStatusType())
517             {
518             case CertificateStatusType.ocsp:
519             {
520                 OCSPResponse ocspResponse = certificateStatus.getOCSPResponse();
521                 return Collections.singletonList(getStatusResponse(ocspResponse));
522             }
523             case CertificateStatusType.ocsp_multi:
524             {
525                 @SuppressWarnings("unchecked")
526                 Vector<OCSPResponse> ocspResponseList = certificateStatus.getOCSPResponseList();
527                 int count = ocspResponseList.size();
528 
529                 ArrayList<byte[]> statusResponses = new ArrayList<byte[]>(count);
530                 for (int i = 0; i < count; ++i)
531                 {
532                     OCSPResponse ocspResponse = (OCSPResponse)ocspResponseList.elementAt(i);
533                     statusResponses.add(getStatusResponse(ocspResponse));
534                 }
535 
536                 return Collections.unmodifiableList(statusResponses);
537             }
538             }
539         }
540         return null;
541     }
542 
getTrustedIssuers(Vector<TrustedAuthority> trustedCAKeys)543     static X500Principal[] getTrustedIssuers(Vector<TrustedAuthority> trustedCAKeys) throws IOException
544     {
545         if (null == trustedCAKeys || trustedCAKeys.isEmpty())
546         {
547             return null;
548         }
549 
550         int count = trustedCAKeys.size();
551         X500Principal[] principals = new X500Principal[count];
552         for (int i = 0; i < count; ++i)
553         {
554             TrustedAuthority trustedAuthority = (TrustedAuthority)trustedCAKeys.get(i);
555             if (IdentifierType.x509_name != trustedAuthority.getIdentifierType())
556             {
557                 // TODO We currently only support the trusted_ca_keys extension if EVERY entry is an x509_name
558                 return null;
559             }
560 
561             principals[i] = toX500Principal(trustedAuthority.getX509Name());
562         }
563         return principals;
564     }
565 
getX509Certificate(JcaTlsCrypto crypto, TlsCertificate tlsCertificate)566     static X509Certificate getX509Certificate(JcaTlsCrypto crypto, TlsCertificate tlsCertificate) throws IOException
567     {
568         return JcaTlsCertificate.convert(crypto, tlsCertificate).getX509Certificate();
569     }
570 
getX509CertificateChain(JcaTlsCrypto crypto, Certificate certificateMessage)571     static X509Certificate[] getX509CertificateChain(JcaTlsCrypto crypto, Certificate certificateMessage)
572     {
573         if (certificateMessage == null || certificateMessage.isEmpty())
574         {
575             return EMPTY_X509CERTIFICATES;
576         }
577 
578         try
579         {
580             X509Certificate[] chain = new X509Certificate[certificateMessage.getLength()];
581             for (int i = 0; i < chain.length; ++i)
582             {
583                 chain[i] = JcaTlsCertificate.convert(crypto, certificateMessage.getCertificateAt(i)).getX509Certificate();
584             }
585             return chain;
586         }
587         catch (IOException e)
588         {
589             // TODO[jsse] Logging
590             throw new RuntimeException(e);
591         }
592     }
593 
getX509CertificateChain(java.security.cert.Certificate[] chain)594     static X509Certificate[] getX509CertificateChain(java.security.cert.Certificate[] chain)
595     {
596         if (chain == null)
597         {
598             return null;
599         }
600         if (chain instanceof X509Certificate[])
601         {
602             return JsseUtils.containsNull(chain) ? null : (X509Certificate[])chain;
603         }
604         X509Certificate[] x509Chain = new X509Certificate[chain.length];
605         for (int i = 0; i < chain.length; ++i)
606         {
607             java.security.cert.Certificate c = chain[i];
608             if (!(c instanceof X509Certificate))
609             {
610                 return null;
611             }
612             x509Chain[i] = (X509Certificate)c;
613         }
614         return x509Chain;
615     }
616 
getSubject(JcaTlsCrypto crypto, Certificate certificateMessage)617     static X500Principal getSubject(JcaTlsCrypto crypto, Certificate certificateMessage)
618     {
619         if (certificateMessage == null || certificateMessage.isEmpty())
620         {
621             return null;
622         }
623 
624         try
625         {
626             return getX509Certificate(crypto, certificateMessage.getCertificateAt(0)).getSubjectX500Principal();
627         }
628         catch (IOException e)
629         {
630             // TODO[jsse] Logging
631             throw new RuntimeException(e);
632         }
633     }
634 
getAlertLogMessage(String root, short alertLevel, short alertDescription)635     static String getAlertLogMessage(String root, short alertLevel, short alertDescription)
636     {
637         return root + " " + AlertLevel.getText(alertLevel) + " " + AlertDescription.getText(alertDescription) + " alert";
638     }
639 
getKeyAlgorithm(Key key)640     static String getKeyAlgorithm(Key key)
641     {
642         if (key instanceof PrivateKey)
643         {
644             return getPrivateKeyAlgorithm((PrivateKey)key);
645         }
646         if (key instanceof PublicKey)
647         {
648             return getPublicKeyAlgorithm((PublicKey)key);
649         }
650         return key.getAlgorithm();
651     }
652 
getPrivateKeyAlgorithm(PrivateKey privateKey)653     static String getPrivateKeyAlgorithm(PrivateKey privateKey)
654     {
655         String algorithm = privateKey.getAlgorithm();
656 
657         /*
658          * TODO[fips] Early BCFIPS versions didn't return standard name for PSS keys. Once the
659          * minimum BCFIPS version no longer has that problem, this handler can be removed.
660          */
661         if ("RSA".equalsIgnoreCase(algorithm))
662         {
663             PrivateKeyInfo pki = PrivateKeyInfo.getInstance(privateKey.getEncoded());
664             if (PKCSObjectIdentifiers.id_RSASSA_PSS.equals(pki.getPrivateKeyAlgorithm().getAlgorithm()))
665             {
666                 return "RSASSA-PSS";
667             }
668         }
669 
670         return algorithm;
671     }
672 
getPublicKeyAlgorithm(PublicKey publicKey)673     static String getPublicKeyAlgorithm(PublicKey publicKey)
674     {
675         String algorithm = publicKey.getAlgorithm();
676 
677         /*
678          * TODO[fips] Early BCFIPS versions didn't return standard name for PSS keys. Once the
679          * minimum BCFIPS version no longer has that problem, this handler can be removed.
680          */
681         if ("RSA".equalsIgnoreCase(algorithm))
682         {
683             SubjectPublicKeyInfo spki = SubjectPublicKeyInfo.getInstance(publicKey.getEncoded());
684             if (PKCSObjectIdentifiers.id_RSASSA_PSS.equals(spki.getAlgorithm().getAlgorithm()))
685             {
686                 return "RSASSA-PSS";
687             }
688         }
689 
690         return algorithm;
691     }
692 
isNameSpecified(String name)693     static boolean isNameSpecified(String name)
694     {
695         return !isNullOrEmpty(name);
696     }
697 
isNullOrEmpty(String s)698     static boolean isNullOrEmpty(String s)
699     {
700         return null == s || s.length() < 1;
701     }
702 
isTLSv12(String protocol)703     static boolean isTLSv12(String protocol)
704     {
705         ProtocolVersion protocolVersion = ProvSSLContextSpi.getProtocolVersion(protocol);
706 
707         return null != protocolVersion && TlsUtils.isTLSv12(protocolVersion);
708     }
709 
isTLSv13(String protocol)710     static boolean isTLSv13(String protocol)
711     {
712         ProtocolVersion protocolVersion = ProvSSLContextSpi.getProtocolVersion(protocol);
713 
714         return null != protocolVersion && TlsUtils.isTLSv13(protocolVersion);
715     }
716 
toX500Principal(X500Name name)717     static X500Principal toX500Principal(X500Name name) throws IOException
718     {
719         return null == name ? null : new X500Principal(name.getEncoded(ASN1Encoding.DER));
720     }
721 
toX500Principals(Vector<X500Name> names)722     static X500Principal[] toX500Principals(Vector<X500Name> names) throws IOException
723     {
724         if (null == names)
725         {
726             return null;
727         }
728 
729         Set<X500Principal> principals = new LinkedHashSet<X500Principal>();
730 
731         int count = names.size();
732         for (int i = 0; i < count; ++i)
733         {
734             X500Principal principal = toX500Principal(names.get(i));
735             if (null != principal)
736             {
737                 principals.add(principal);
738             }
739         }
740 
741         return principals.toArray(new X500Principal[0]);
742     }
743 
convertSNIServerName(ServerName serverName)744     static BCSNIServerName convertSNIServerName(ServerName serverName)
745     {
746         short nameType = serverName.getNameType();
747         byte[] nameData = serverName.getNameData();
748 
749         switch (nameType)
750         {
751         case BCStandardConstants.SNI_HOST_NAME:
752             return new BCSNIHostName(nameData);
753         default:
754             return new BCUnknownServerName(nameType, nameData);
755         }
756     }
757 
convertSNIServerNames(Vector<ServerName> serverNameList)758     static List<BCSNIServerName> convertSNIServerNames(Vector<ServerName> serverNameList)
759     {
760         if (null == serverNameList || serverNameList.isEmpty())
761         {
762             return Collections.emptyList();
763         }
764 
765         ArrayList<BCSNIServerName> result = new ArrayList<BCSNIServerName>(serverNameList.size());
766 
767         Enumeration<ServerName> serverNames = serverNameList.elements();
768         while (serverNames.hasMoreElements())
769         {
770             result.add(convertSNIServerName(serverNames.nextElement()));
771         }
772 
773         return Collections.unmodifiableList(result);
774     }
775 
findMatchingSNIServerName(Vector<ServerName> serverNameList, Collection<BCSNIMatcher> sniMatchers)776     static BCSNIServerName findMatchingSNIServerName(Vector<ServerName> serverNameList,
777         Collection<BCSNIMatcher> sniMatchers)
778     {
779         if (!serverNameList.isEmpty())
780         {
781             List<BCSNIServerName> sniServerNames = convertSNIServerNames(serverNameList);
782             for (BCSNIMatcher sniMatcher : sniMatchers)
783             {
784                 if (null != sniMatcher)
785                 {
786                     int nameType = sniMatcher.getType();
787                     for (BCSNIServerName sniServerName : sniServerNames)
788                     {
789                         if (null == sniServerName || sniServerName.getType() != nameType)
790                         {
791                             continue;
792                         }
793                         if (sniMatcher.matches(sniServerName))
794                         {
795                             return sniServerName;
796                         }
797                         break;
798                     }
799                 }
800             }
801         }
802 
803         return null;
804     }
805 
getSNIHostName(List<BCSNIServerName> serverNames)806     static BCSNIHostName getSNIHostName(List<BCSNIServerName> serverNames)
807     {
808         if (null != serverNames)
809         {
810             for (BCSNIServerName serverName : serverNames)
811             {
812                 if (null != serverName && BCStandardConstants.SNI_HOST_NAME == serverName.getType())
813                 {
814                     if (serverName instanceof BCSNIHostName)
815                     {
816                         return (BCSNIHostName)serverName;
817                     }
818 
819                     try
820                     {
821                         return new BCSNIHostName(serverName.getEncoded());
822                     }
823                     catch (RuntimeException e)
824                     {
825                         return null;
826                     }
827                 }
828             }
829         }
830         return null;
831     }
832 
removeAllWhitespace(String s)833     static String removeAllWhitespace(String s)
834     {
835         if (isNullOrEmpty(s))
836         {
837             return s;
838         }
839 
840         int originalLength = s.length();
841         char[] buf = new char[originalLength];
842         int bufPos = 0;
843 
844         for (int i = 0; i < originalLength; ++i)
845         {
846             char c = s.charAt(i);
847             if (!Character.isWhitespace(c))
848             {
849                 buf[bufPos++] = c;
850             }
851         }
852 
853         if (bufPos == 0)
854         {
855             return EMPTY_STRING;
856         }
857         if (bufPos == originalLength)
858         {
859             return s;
860         }
861         return new String(buf, 0, bufPos);
862     }
863 
requireCloseNotify()864     static boolean requireCloseNotify()
865     {
866         return provTlsRequireCloseNotify;
867     }
868 
stripDoubleQuotes(String s)869     static String stripDoubleQuotes(String s)
870     {
871         return stripOuterChars(s, '"', '"');
872     }
873 
stripSquareBrackets(String s)874     static String stripSquareBrackets(String s)
875     {
876         return stripOuterChars(s, '[', ']');
877     }
878 
stripOuterChars(String s, char openChar, char closeChar)879     private static String stripOuterChars(String s, char openChar, char closeChar)
880     {
881         if (s != null)
882         {
883             int sLast = s.length() - 1;
884             if (sLast > 0 && s.charAt(0) == openChar && s.charAt(sLast) == closeChar)
885             {
886                 return s.substring(1, sLast);
887             }
888         }
889         return s;
890     }
891 
useExtendedMasterSecret()892     static boolean useExtendedMasterSecret()
893     {
894         return provTlsUseExtendedMasterSecret;
895     }
896 }
897