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