1 module hunt.net.secure.conscrypt.SSLParametersImpl; 2 3 // dfmt off 4 version(WITH_HUNT_SECURITY): 5 // dfmt on 6 7 import hunt.net.secure.conscrypt.AbstractSessionContext; 8 import hunt.net.secure.conscrypt.ApplicationProtocolSelectorAdapter; 9 import hunt.net.secure.conscrypt.ClientSessionContext; 10 import hunt.net.secure.conscrypt.NativeCrypto; 11 import hunt.net.secure.conscrypt.ServerSessionContext; 12 import hunt.net.secure.conscrypt.SSLUtils; 13 14 // import hunt.net.ssl.KeyManager; 15 // import hunt.net.ssl.KeyManagerFactory; 16 // import hunt.net.ssl.X509KeyManager; 17 // import hunt.net.ssl.X509TrustManager; 18 import hunt.net.KeyCertOptions; 19 20 // import hunt.security.Key; 21 // import hunt.security.cert.X509Certificate; 22 // import hunt.security.x500.X500Principal; 23 24 import hunt.Exceptions; 25 import hunt.logging; 26 import hunt.util.Common; 27 import hunt.util.ObjectUtils; 28 29 /** 30 * The instances of this class encapsulate all the info 31 * about enabled cipher suites and protocols, 32 * as well as the information about client/server mode of 33 * ssl socket, whether it require/want client authentication or not, 34 * and controls whether new SSL sessions may be established by this 35 * socket or not. 36 */ 37 final class SSLParametersImpl : Cloneable { 38 39 // // default source of X.509 certificate based authentication keys 40 // private static X509KeyManager defaultX509KeyManager; 41 // default source of X.509 certificate based authentication trust decisions 42 // private static X509TrustManager defaultX509TrustManager; 43 44 // default SSL parameters 45 // private static SSLParametersImpl defaultParameters; 46 47 // client session context contains the set of reusable 48 // client-side SSL sessions 49 private ClientSessionContext clientSessionContext; 50 // server session context contains the set of reusable 51 // server-side SSL sessions 52 private ServerSessionContext serverSessionContext; 53 // source of X.509 certificate based authentication keys or null if not provided 54 // private X509KeyManager x509KeyManager; 55 // source of Pre-Shared Key (PSK) authentication keys or null if not provided. 56 // @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 57 // private PSKKeyManager pskKeyManager; 58 // source of X.509 certificate based authentication trust decisions or null if not provided 59 // private X509TrustManager x509TrustManager; 60 61 // protocols enabled for SSL connection 62 string[] enabledProtocols; 63 // set to indicate when obsolete protocols are filtered 64 bool isEnabledProtocolsFiltered; 65 // cipher suites enabled for SSL connection 66 string[] enabledCipherSuites; 67 68 // if the peer with this parameters tuned to work in client mode 69 private bool client_mode = true; 70 // if the peer with this parameters tuned to require client authentication 71 private bool need_client_auth = false; 72 // if the peer with this parameters tuned to request client authentication 73 private bool want_client_auth = false; 74 // if the peer with this parameters allowed to cteate new SSL session 75 private bool enable_session_creation = true; 76 // Endpoint identification algorithm (e.g., HTTPS) 77 private string endpointIdentificationAlgorithm; 78 // Whether to use the local cipher suites order 79 private bool useCipherSuitesOrder; 80 81 // client-side only, bypasses the property based configuration, used for tests 82 private bool ctVerificationEnabled; 83 84 // server-side only. SCT and OCSP data to send to clients which request it 85 byte[] sctExtension; 86 byte[] ocspResponse; 87 88 ubyte[] applicationProtocols = []; 89 ApplicationProtocolSelectorAdapter applicationProtocolSelector; 90 bool useSessionTickets; 91 private bool useSni; 92 93 private KeyCertOptions _keyCertOptions; 94 95 /** 96 * Whether the TLS Channel ID extension is enabled. This field is 97 * server-side only. 98 */ 99 bool channelIdEnabled; 100 101 private this() { 102 // It's only used for the creation in reflection. 103 } 104 105 /** 106 * Initializes the parameters. Naturally this constructor is used 107 * in SSLContextImpl.engineInit method which directly passes its 108 * parameters. In other words this constructor holds all 109 * the functionality provided by SSLContext.init method. 110 * See {@link javax.net.ssl.SSLContext#init(KeyManager[],TrustManager[], 111 * SecureRandom)} for more information 112 */ 113 this(KeyCertOptions options, ClientSessionContext clientSessionContext, 114 ServerSessionContext serverSessionContext, string[] protocols) { 115 _keyCertOptions = options; 116 this.serverSessionContext = serverSessionContext; 117 this.clientSessionContext = clientSessionContext; 118 } 119 // this(KeyManager[] kms, TrustManager[] tms, ClientSessionContext clientSessionContext, 120 // ServerSessionContext serverSessionContext, string[] protocols) { 121 // this.serverSessionContext = serverSessionContext; 122 // this.clientSessionContext = clientSessionContext; 123 124 // version(Have_boringssl) { 125 // // initialize key managers 126 // if (kms is null) { 127 // x509KeyManager = getDefaultX509KeyManager(); 128 // // There's no default PSK key manager 129 // // pskKeyManager = null; 130 // } else { 131 // x509KeyManager = findFirstX509KeyManager(kms); 132 // // pskKeyManager = findFirstPSKKeyManager(kms); 133 // } 134 135 // // initialize x509TrustManager 136 // if (tms is null) { 137 // x509TrustManager = getDefaultX509TrustManager(); 138 // } else { 139 // x509TrustManager = findFirstX509TrustManager(tms); 140 // } 141 142 // // initialize the list of cipher suites and protocols enabled by default 143 // enabledProtocols = NativeCrypto.checkEnabledProtocols( 144 // protocols is null ? NativeCrypto.DEFAULT_PROTOCOLS : protocols).dup; 145 // bool x509CipherSuitesNeeded = (x509KeyManager !is null) || (x509TrustManager !is null); 146 // bool pskCipherSuitesNeeded = false; // pskKeyManager !is null; 147 // enabledCipherSuites = getDefaultCipherSuites( 148 // x509CipherSuitesNeeded, pskCipherSuitesNeeded); 149 // } 150 // // We ignore the SecureRandom passed in by the caller. The native code below 151 // // directly accesses /dev/urandom, which makes it irrelevant. 152 // } 153 154 KeyCertOptions getKeyCertOptions() { 155 return _keyCertOptions; 156 } 157 158 /** 159 * Returns the appropriate session context. 160 */ 161 AbstractSessionContext getSessionContext() { 162 return client_mode ? clientSessionContext : serverSessionContext; 163 } 164 165 /** 166 * @return client session context 167 */ 168 ClientSessionContext getClientSessionContext() { 169 return clientSessionContext; 170 } 171 172 /** 173 * @return X.509 key manager or {@code null} for none. 174 */ 175 // X509KeyManager getX509KeyManager() { 176 // return x509KeyManager; 177 // } 178 179 // /** 180 // * @return Pre-Shared Key (PSK) key manager or {@code null} for none. 181 // */ 182 // @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 183 // PSKKeyManager getPSKKeyManager() { 184 // return pskKeyManager; 185 // } 186 187 // /** 188 // * @return X.509 trust manager or {@code null} for none. 189 // */ 190 // X509TrustManager getX509TrustManager() { 191 // return x509TrustManager; 192 // } 193 194 /** 195 * @return the names of enabled cipher suites 196 */ 197 string[] getEnabledCipherSuites() { 198 return enabledCipherSuites.dup; 199 } 200 201 /** 202 * Sets the enabled cipher suites after filtering through OpenSSL. 203 */ 204 void setEnabledCipherSuites(string[] cipherSuites) { 205 enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(cipherSuites).dup; 206 } 207 208 /** 209 * @return the set of enabled protocols 210 */ 211 string[] getEnabledProtocols() { 212 return enabledProtocols.dup; 213 } 214 215 /** 216 * Sets the list of available protocols for use in SSL connection. 217 * @throws IllegalArgumentException if {@code protocols is null} 218 */ 219 void setEnabledProtocols(string[] protocols) { 220 if (protocols is null) { 221 throw new IllegalArgumentException("protocols is null"); 222 } 223 string[] filteredProtocols = 224 filterFromProtocols(protocols, NativeCrypto.OBSOLETE_PROTOCOL_SSLV3); 225 isEnabledProtocolsFiltered = protocols.length != filteredProtocols.length; 226 enabledProtocols = NativeCrypto.checkEnabledProtocols(filteredProtocols).dup; 227 } 228 229 /** 230 * Sets the list of ALPN protocols. 231 * 232 * @param protocols the list of ALPN protocols 233 */ 234 void setApplicationProtocols(string[] protocols) { 235 this.applicationProtocols = cast(ubyte[])SSLUtils.encodeProtocols(protocols); 236 } 237 238 string[] getApplicationProtocols() { 239 return SSLUtils.decodeProtocols(applicationProtocols); 240 } 241 242 /** 243 * Used for server-mode only. Sets or clears the application-provided ALPN protocol selector. 244 * If set, will override the protocol list provided by {@link #setApplicationProtocols(string[])}. 245 */ 246 void setApplicationProtocolSelector(ApplicationProtocolSelectorAdapter applicationProtocolSelector) { 247 this.applicationProtocolSelector = applicationProtocolSelector; 248 } 249 250 /** 251 * Tunes the peer holding this parameters to work in client mode. 252 * @param mode if the peer is configured to work in client mode 253 */ 254 void setUseClientMode(bool mode) { 255 client_mode = mode; 256 } 257 258 /** 259 * Returns the value indicating if the parameters configured to work 260 * in client mode. 261 */ 262 bool getUseClientMode() { 263 return client_mode; 264 } 265 266 /** 267 * Tunes the peer holding this parameters to require client authentication 268 */ 269 void setNeedClientAuth(bool need) { 270 need_client_auth = need; 271 // reset the want_client_auth setting 272 want_client_auth = false; 273 } 274 275 /** 276 * Returns the value indicating if the peer with this parameters tuned 277 * to require client authentication 278 */ 279 bool getNeedClientAuth() { 280 return need_client_auth; 281 } 282 283 /** 284 * Tunes the peer holding this parameters to request client authentication 285 */ 286 void setWantClientAuth(bool want) { 287 want_client_auth = want; 288 // reset the need_client_auth setting 289 need_client_auth = false; 290 } 291 292 /** 293 * Returns the value indicating if the peer with this parameters 294 * tuned to request client authentication 295 */ 296 bool getWantClientAuth() { 297 return want_client_auth; 298 } 299 300 /** 301 * Allows/disallows the peer holding this parameters to 302 * create new SSL session 303 */ 304 void setEnableSessionCreation(bool flag) { 305 enable_session_creation = flag; 306 } 307 308 /** 309 * Returns the value indicating if the peer with this parameters 310 * allowed to cteate new SSL session 311 */ 312 bool getEnableSessionCreation() { 313 return enable_session_creation; 314 } 315 316 void setUseSessionTickets(bool useSessionTickets) { 317 this.useSessionTickets = useSessionTickets; 318 } 319 320 /** 321 * Whether connections using this SSL connection should use the TLS 322 * extension Server Name Indication (SNI). 323 */ 324 void setUseSni(bool flag) { 325 useSni = flag; 326 } 327 328 /** 329 * Returns whether connections using this SSL connection should use the TLS 330 * extension Server Name Indication (SNI). 331 */ 332 bool getUseSni() { 333 return useSni ? useSni : isSniEnabledByDefault(); 334 } 335 336 /** 337 * For testing only. 338 */ 339 void setCTVerificationEnabled(bool enabled) { 340 ctVerificationEnabled = enabled; 341 } 342 343 /** 344 * For testing only. 345 */ 346 void setSCTExtension(byte[] extension) { 347 sctExtension = extension; 348 } 349 350 /** 351 * For testing only. 352 */ 353 void setOCSPResponse(byte[] response) { 354 ocspResponse = response; 355 } 356 357 byte[] getOCSPResponse() { 358 return ocspResponse; 359 } 360 361 /** 362 * This filters {@code obsoleteProtocol} from the list of {@code protocols} 363 * down to help with app compatibility. 364 */ 365 private static string[] filterFromProtocols(string[] protocols, string obsoleteProtocol) { 366 if (protocols.length == 1 && obsoleteProtocol == protocols[0]) { 367 return []; 368 } 369 370 string[] newProtocols; 371 foreach (string protocol ; protocols) { 372 if (obsoleteProtocol != protocol) { 373 newProtocols ~= protocol; 374 } 375 } 376 return newProtocols; 377 } 378 379 /** 380 * Returns whether Server Name Indication (SNI) is enabled by default for 381 * sockets. For more information on SNI, see RFC 6066 section 3. 382 */ 383 private bool isSniEnabledByDefault() { 384 return false; 385 // try { 386 // string enableSNI = System.getProperty("jsse.enableSNIExtension", "true"); 387 // if ("true".equalsIgnoreCase(enableSNI)) { 388 // return true; 389 // } else if ("false".equalsIgnoreCase(enableSNI)) { 390 // return false; 391 // } else { 392 // throw new RuntimeException( 393 // "Can only set \"jsse.enableSNIExtension\" to \"true\" or \"false\""); 394 // } 395 // } catch (SecurityException e) { 396 // return true; 397 // } 398 } 399 400 /** 401 * Returns the clone of this object. 402 * @return the clone. 403 */ 404 mixin CloneMemberTemplate!(typeof(this), TopLevel.no, (typeof(this) from, typeof(this) to) { 405 // FIXME: Needing refactor or cleanup -@zxp at 6/10/2019, 3:22:38 PM 406 // need to check this 407 }); 408 409 410 // private static X509KeyManager getDefaultX509KeyManager() { 411 // X509KeyManager result = defaultX509KeyManager; 412 // if (result is null) { 413 // // single-check idiom 414 // defaultX509KeyManager = result = createDefaultX509KeyManager(); 415 // } 416 // return result; 417 // } 418 419 // private static X509KeyManager createDefaultX509KeyManager() { 420 // try { 421 // // string algorithm = KeyManagerFactory.getDefaultAlgorithm(); 422 // // KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); 423 // // kmf.init(null, null); 424 // // KeyManager[] kms = kmf.getKeyManagers(); 425 // // X509KeyManager result = findFirstX509KeyManager(kms); 426 // // if (result is null) { 427 // // throw new KeyManagementException("No X509KeyManager among default KeyManagers: " 428 // // ~ kms.to!string()); 429 // // } 430 // // return result; 431 // implementationMissing(false); 432 // return null; 433 // } catch (NoSuchAlgorithmException e) { 434 // throw new KeyManagementException(e); 435 // } catch (KeyStoreException e) { 436 // throw new KeyManagementException(e); 437 // } catch (UnrecoverableKeyException e) { 438 // throw new KeyManagementException(e); 439 // } 440 // } 441 442 /** 443 * Finds the first {@link X509KeyManager} element in the provided array. 444 * 445 * @return the first {@code X509KeyManager} or {@code null} if not found. 446 */ 447 // private static X509KeyManager findFirstX509KeyManager(KeyManager[] kms) { 448 // foreach (KeyManager km ; kms) { 449 // X509KeyManager m = cast(X509KeyManager)km; 450 // if (m !is null) { 451 // return m; 452 // } 453 // } 454 // warning("X509KeyManager is null"); 455 // return null; 456 // } 457 458 // /** 459 // * Finds the first {@link PSKKeyManager} element in the provided array. 460 // * 461 // * @return the first {@code PSKKeyManager} or {@code null} if not found. 462 // */ 463 // @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 464 // private static PSKKeyManager findFirstPSKKeyManager(KeyManager[] kms) { 465 // for (KeyManager km : kms) { 466 // if (km instanceof PSKKeyManager) { 467 // return (PSKKeyManager)km; 468 // } else if (km !is null) { 469 // try { 470 // return DuckTypedPSKKeyManager.getInstance(km); 471 // } catch (NoSuchMethodException ignored) {} 472 // } 473 // } 474 // return null; 475 // } 476 477 /** 478 * Gets the default X.509 trust manager. 479 */ 480 // static X509TrustManager getDefaultX509TrustManager() 481 // { 482 // X509TrustManager result = defaultX509TrustManager; 483 // if (result is null) { 484 // // single-check idiom 485 // // defaultX509TrustManager = result = createDefaultX509TrustManager(); 486 // } 487 // return result; 488 // } 489 490 // private static X509TrustManager createDefaultX509TrustManager() 491 // { 492 // try { 493 // string algorithm = TrustManagerFactory.getDefaultAlgorithm(); 494 // TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); 495 // tmf.init((KeyStore) null); 496 // TrustManager[] tms = tmf.getTrustManagers(); 497 // X509TrustManager trustManager = findFirstX509TrustManager(tms); 498 // if (trustManager is null) { 499 // throw new KeyManagementException( 500 // "No X509TrustManager in among default TrustManagers: " 501 // + Arrays.toString(tms)); 502 // } 503 // return trustManager; 504 // } catch (NoSuchAlgorithmException e) { 505 // throw new KeyManagementException(e); 506 // } catch (KeyStoreException e) { 507 // throw new KeyManagementException(e); 508 // } 509 // } 510 511 /** 512 * Finds the first {@link X509TrustManager} element in the provided array. 513 * 514 * @return the first {@code X509ExtendedTrustManager} or 515 * {@code X509TrustManager} or {@code null} if not found. 516 */ 517 // private static X509TrustManager findFirstX509TrustManager(TrustManager[] tms) { 518 // foreach (TrustManager tm ; tms) { 519 // X509TrustManager m = cast(X509TrustManager) tm; 520 // if (m !is null) { 521 // return m; 522 // } 523 // } 524 // return null; 525 // } 526 527 // string getEndpointIdentificationAlgorithm() { 528 // return endpointIdentificationAlgorithm; 529 // } 530 531 // void setEndpointIdentificationAlgorithm(string endpointIdentificationAlgorithm) { 532 // this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm; 533 // } 534 535 // bool getUseCipherSuitesOrder() { 536 // return useCipherSuitesOrder; 537 // } 538 539 // void setUseCipherSuitesOrder(bool useCipherSuitesOrder) { 540 // this.useCipherSuitesOrder = useCipherSuitesOrder; 541 // } 542 543 private static string[] getDefaultCipherSuites( 544 bool x509CipherSuitesNeeded, 545 bool pskCipherSuitesNeeded) { 546 if (x509CipherSuitesNeeded) { 547 // X.509 based cipher suites need to be listed. 548 if (pskCipherSuitesNeeded) { 549 // Both X.509 and PSK based cipher suites need to be listed. Because TLS-PSK is not 550 // normally used, we assume that when PSK cipher suites are requested here they 551 // should be preferred over other cipher suites. Thus, we give PSK cipher suites 552 // higher priority than X.509 cipher suites. 553 // NOTE: There are cipher suites that use both X.509 and PSK (e.g., those based on 554 // RSA_PSK key exchange). However, these cipher suites are not currently supported. 555 return NativeCrypto.DEFAULT_PSK_CIPHER_SUITES ~ 556 NativeCrypto.DEFAULT_X509_CIPHER_SUITES ~ 557 [ NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ]; 558 } else { 559 // Only X.509 cipher suites need to be listed. 560 return NativeCrypto.DEFAULT_X509_CIPHER_SUITES ~ 561 [ NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ]; 562 } 563 } else if (pskCipherSuitesNeeded) { 564 // Only PSK cipher suites need to be listed. 565 return NativeCrypto.DEFAULT_PSK_CIPHER_SUITES ~ 566 [ NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ]; 567 } else { 568 // Neither X.509 nor PSK cipher suites need to be listed. 569 return [ NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ]; 570 } 571 } 572 573 // private static string[] concat(string[]... arrays) { 574 // int resultLength = 0; 575 // for (string[] array : arrays) { 576 // resultLength += array.length; 577 // } 578 // string[] result = new string[resultLength]; 579 // int resultOffset = 0; 580 // for (string[] array : arrays) { 581 // System.arraycopy(array, 0, result, resultOffset, array.length); 582 // resultOffset += array.length; 583 // } 584 // return result; 585 // } 586 587 /** 588 * Check if SCT verification is enforced for a given hostname. 589 */ 590 bool isCTVerificationEnabled(string hostname) { 591 if (hostname is null) { 592 return false; 593 } 594 595 // Bypass the check. This is used for testing only 596 if (ctVerificationEnabled) { 597 return true; 598 } 599 // return Platform.isCTVerificationRequired(hostname); 600 implementationMissing(); 601 return false; 602 } 603 } 604 605 606 /** 607 * For abstracting the X509KeyManager calls between 608 * {@link X509KeyManager#chooseClientAlias(string[], java.security.Principal[], java.net.Socket)} 609 * and 610 * {@link X509ExtendedKeyManager#chooseEngineClientAlias(string[], java.security.Principal[], javax.net.ssl.SSLEngine)} 611 */ 612 // interface AliasChooser { 613 // string chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers, 614 // string[] keyTypes); 615 616 // string chooseServerAlias(X509KeyManager keyManager, string keyType); 617 // } 618 619 /** 620 * For abstracting the {@code PSKKeyManager} calls between those taking an {@code SSLSocket} and 621 * those taking an {@code SSLEngine}. 622 */ 623 // @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 624 // interface PSKCallbacks { 625 // // string chooseServerPSKIdentityHint(PSKKeyManager keyManager); 626 // // string chooseClientPSKIdentity(PSKKeyManager keyManager, string identityHint); 627 // // SecretKey getPSKKey(PSKKeyManager keyManager, string identityHint, string identity); 628 // }