1 module hunt.net.secure.conscrypt.Conscrypt; 2 3 // dfmt off 4 version(WITH_HUNT_SECURITY): 5 // dfmt on 6 7 import hunt.net.secure.conscrypt.AbstractConscryptEngine; 8 import hunt.net.secure.conscrypt.ApplicationProtocolSelector; 9 import hunt.net.secure.conscrypt.NativeConstants; 10 11 import hunt.net.ssl.SSLEngine; 12 13 14 import hunt.net.Exceptions; 15 import hunt.Exceptions; 16 17 /** 18 * Core API for creating and configuring all Conscrypt types. 19 */ 20 21 final class Conscrypt { 22 private this() {} 23 24 /** 25 * Returns {@code true} if the Conscrypt native library has been successfully loaded. 26 */ 27 static bool isAvailable() { 28 try { 29 checkAvailability(); 30 return true; 31 } catch (Exception e) { 32 return false; 33 } 34 } 35 36 /** 37 * Checks that the Conscrypt support is available for the system. 38 * 39 * @throws UnsatisfiedLinkError if unavailable 40 */ 41 static void checkAvailability() { 42 // NativeCrypto.checkAvailability(); 43 } 44 45 /** 46 * Indicates whether the given {@link Provider} was created by this distribution of Conscrypt. 47 */ 48 // static bool isConscrypt(Provider provider) { 49 // return provider instanceof OpenSSLProvider; 50 // } 51 52 /** 53 * Constructs a new {@link Provider} with the default name. 54 */ 55 // static Provider newProvider() { 56 // checkAvailability(); 57 // return new OpenSSLProvider(); 58 // } 59 60 /** 61 * Constructs a new {@link Provider} with the given name. 62 */ 63 // static Provider newProvider(string providerName) { 64 // checkAvailability(); 65 // return new OpenSSLProvider(providerName); 66 // } 67 68 /** 69 * Returns the maximum length (in bytes) of an encrypted packet. 70 */ 71 static int maxEncryptedPacketLength() { 72 return NativeConstants.SSL3_RT_MAX_PACKET_SIZE; 73 } 74 75 // /** 76 // * Gets the default X.509 trust manager. 77 // */ 78 // @ExperimentalApi 79 // static X509TrustManager getDefaultX509TrustManager() { 80 // checkAvailability(); 81 // return SSLParametersImpl.getDefaultX509TrustManager(); 82 // } 83 84 // /** 85 // * Indicates whether the given {@link SSLContext} was created by this distribution of Conscrypt. 86 // */ 87 // static bool isConscrypt(SSLContext context) { 88 // return context.getProvider() instanceof OpenSSLProvider; 89 // } 90 91 // /** 92 // * Constructs a new instance of the preferred {@link SSLContextSpi}. 93 // */ 94 // static SSLContextSpi newPreferredSSLContextSpi() { 95 // checkAvailability(); 96 // return OpenSSLContextImpl.getPreferred(); 97 // } 98 99 // /** 100 // * Sets the client-side persistent cache to be used by the context. 101 // */ 102 // static void setClientSessionCache(SSLContext context, SSLClientSessionCache cache) { 103 // SSLSessionContext clientContext = context.getClientSessionContext(); 104 // if (!(clientContext instanceof ClientSessionContext)) { 105 // throw new IllegalArgumentException( 106 // "Not a conscrypt client context: " ~ clientContext.getClass().getName()); 107 // } 108 // ((ClientSessionContext) clientContext).setPersistentCache(cache); 109 // } 110 111 // /** 112 // * Sets the server-side persistent cache to be used by the context. 113 // */ 114 // static void setServerSessionCache(SSLContext context, SSLServerSessionCache cache) { 115 // SSLSessionContext serverContext = context.getServerSessionContext(); 116 // if (!(serverContext instanceof ServerSessionContext)) { 117 // throw new IllegalArgumentException( 118 // "Not a conscrypt client context: " ~ serverContext.getClass().getName()); 119 // } 120 // ((ServerSessionContext) serverContext).setPersistentCache(cache); 121 // } 122 123 /** 124 * Indicates whether the given {@link SSLSocketFactory} was created by this distribution of 125 * Conscrypt. 126 */ 127 // static bool isConscrypt(SSLSocketFactory factory) { 128 // return typeid(factory) == typeid(OpenSSLSocketFactoryImpl); 129 // } 130 131 // private static OpenSSLSocketFactoryImpl toConscrypt(SSLSocketFactory factory) { 132 // if (!isConscrypt(factory)) { 133 // throw new IllegalArgumentException( 134 // "Not a conscrypt socket factory: " ~ factory.getClass().getName()); 135 // } 136 // return (OpenSSLSocketFactoryImpl) factory; 137 // } 138 139 // /** 140 // * Configures the default socket to be created for all socket factory instances. 141 // */ 142 // @ExperimentalApi 143 // static void setUseEngineSocketByDefault(bool useEngineSocket) { 144 // OpenSSLSocketFactoryImpl.setUseEngineSocketByDefault(useEngineSocket); 145 // OpenSSLServerSocketFactoryImpl.setUseEngineSocketByDefault(useEngineSocket); 146 // } 147 148 // /** 149 // * Configures the socket to be created for the given socket factory instance. 150 // */ 151 // @ExperimentalApi 152 // static void setUseEngineSocket(SSLSocketFactory factory, bool useEngineSocket) { 153 // toConscrypt(factory).setUseEngineSocket(useEngineSocket); 154 // } 155 156 // /** 157 // * Indicates whether the given {@link SSLServerSocketFactory} was created by this distribution 158 // * of Conscrypt. 159 // */ 160 // static bool isConscrypt(SSLServerSocketFactory factory) { 161 // return factory instanceof OpenSSLServerSocketFactoryImpl; 162 // } 163 164 // private static OpenSSLServerSocketFactoryImpl toConscrypt(SSLServerSocketFactory factory) { 165 // if (!isConscrypt(factory)) { 166 // throw new IllegalArgumentException( 167 // "Not a conscrypt server socket factory: " ~ factory.getClass().getName()); 168 // } 169 // return (OpenSSLServerSocketFactoryImpl) factory; 170 // } 171 172 // /** 173 // * Configures the socket to be created for the given server socket factory instance. 174 // */ 175 // @ExperimentalApi 176 // static void setUseEngineSocket(SSLServerSocketFactory factory, bool useEngineSocket) { 177 // toConscrypt(factory).setUseEngineSocket(useEngineSocket); 178 // } 179 180 // /** 181 // * Indicates whether the given {@link SSLSocket} was created by this distribution of Conscrypt. 182 // */ 183 // static bool isConscrypt(SSLSocket socket) { 184 // return socket instanceof AbstractConscryptSocket; 185 // } 186 187 // private static AbstractConscryptSocket toConscrypt(SSLSocket socket) { 188 // if (!isConscrypt(socket)) { 189 // throw new IllegalArgumentException( 190 // "Not a conscrypt socket: " ~ socket.getClass().getName()); 191 // } 192 // return (AbstractConscryptSocket) socket; 193 // } 194 195 // /** 196 // * This method enables Server Name Indication (SNI) and overrides the hostname supplied 197 // * during socket creation. If the hostname is not a valid SNI hostname, the SNI extension 198 // * will be omitted from the handshake. 199 // * 200 // * @param socket the socket 201 // * @param hostname the desired SNI hostname, or null to disable 202 // */ 203 // static void setHostname(SSLSocket socket, string hostname) { 204 // toConscrypt(socket).setHostname(hostname); 205 // } 206 207 // /** 208 // * Returns either the hostname supplied during socket creation or via 209 // * {@link #setHostname(SSLSocket, string)}. No DNS resolution is attempted before 210 // * returning the hostname. 211 // */ 212 // static string getHostname(SSLSocket socket) { 213 // return toConscrypt(socket).getHostname(); 214 // } 215 216 // /** 217 // * This method attempts to create a textual representation of the peer host or IP. Does 218 // * not perform a reverse DNS lookup. This is typically used during session creation. 219 // */ 220 // static string getHostnameOrIP(SSLSocket socket) { 221 // return toConscrypt(socket).getHostnameOrIP(); 222 // } 223 224 // /** 225 // * This method enables session ticket support. 226 // * 227 // * @param socket the socket 228 // * @param useSessionTickets True to enable session tickets 229 // */ 230 // static void setUseSessionTickets(SSLSocket socket, bool useSessionTickets) { 231 // toConscrypt(socket).setUseSessionTickets(useSessionTickets); 232 // } 233 234 // /** 235 // * Enables/disables TLS Channel ID for the given server-side socket. 236 // * 237 // * <p>This method needs to be invoked before the handshake starts. 238 // * 239 // * @param socket the socket 240 // * @param enabled Whether to enable channel ID. 241 // * @throws IllegalStateException if this is a client socket or if the handshake has already 242 // * started. 243 // */ 244 // static void setChannelIdEnabled(SSLSocket socket, bool enabled) { 245 // toConscrypt(socket).setChannelIdEnabled(enabled); 246 // } 247 248 // /** 249 // * Gets the TLS Channel ID for the given server-side socket. Channel ID is only available 250 // * once the handshake completes. 251 // * 252 // * @param socket the socket 253 // * @return channel ID or {@code null} if not available. 254 // * @throws IllegalStateException if this is a client socket or if the handshake has not yet 255 // * completed. 256 // * @throws SSLException if channel ID is available but could not be obtained. 257 // */ 258 // static byte[] getChannelId(SSLSocket socket) { 259 // return toConscrypt(socket).getChannelId(); 260 // } 261 262 // /** 263 // * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client socket. 264 // * 265 // * <p>This method needs to be invoked before the handshake starts. 266 // * 267 // * @param socket the socket 268 // * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key 269 // * (disables TLS Channel ID). 270 // * The private key must be an Elliptic Curve (EC) key based on the NIST P-256 curve (aka 271 // * SECG secp256r1 or ANSI 272 // * X9.62 prime256v1). 273 // * @throws IllegalStateException if this is a server socket or if the handshake has already 274 // * started. 275 // */ 276 // static void setChannelIdPrivateKey(SSLSocket socket, PrivateKey privateKey) { 277 // toConscrypt(socket).setChannelIdPrivateKey(privateKey); 278 // } 279 280 // /** 281 // * Returns the ALPN protocol agreed upon by client and server. 282 // * 283 // * @param socket the socket 284 // * @return the selected protocol or {@code null} if no protocol was agreed upon. 285 // */ 286 // static string getApplicationProtocol(SSLSocket socket) { 287 // return toConscrypt(socket).getApplicationProtocol(); 288 // } 289 290 /** 291 * Sets an application-provided ALPN protocol selector. If provided, this will override 292 * the list of protocols set by {@link #setApplicationProtocols(SSLSocket, string[])}. 293 * 294 * @param socket the socket 295 * @param selector the ALPN protocol selector 296 */ 297 // static void setApplicationProtocolSelector(SSLSocket socket, 298 // ApplicationProtocolSelector selector) { 299 // toConscrypt(socket).setApplicationProtocolSelector(selector); 300 // } 301 302 // /** 303 // * Sets the application-layer protocols (ALPN) in prioritization order. 304 // * 305 // * @param socket the socket being configured 306 // * @param protocols the protocols in descending order of preference. If empty, no protocol 307 // * indications will be used. This array will be copied. 308 // * @throws IllegalArgumentException - if protocols is null, or if any element in a non-empty 309 // * array is null or an empty (zero-length) string 310 // */ 311 // static void setApplicationProtocols(SSLSocket socket, string[] protocols) { 312 // toConscrypt(socket).setApplicationProtocols(protocols); 313 // } 314 315 // /** 316 // * Gets the application-layer protocols (ALPN) in prioritization order. 317 // * 318 // * @param socket the socket 319 // * @return the protocols in descending order of preference, or an empty array if protocol 320 // * indications are not being used. Always returns a new array. 321 // */ 322 // static string[] getApplicationProtocols(SSLSocket socket) { 323 // return toConscrypt(socket).getApplicationProtocols(); 324 // } 325 326 // /** 327 // * Returns the tls-unique channel binding value for this connection, per RFC 5929. This 328 // * will return {@code null} if there is no such value available, such as if the handshake 329 // * has not yet completed or this connection is closed. 330 // */ 331 // static byte[] getTlsUnique(SSLSocket socket) { 332 // return toConscrypt(socket).getTlsUnique(); 333 // } 334 335 // /** 336 // * Enables token binding parameter negotiation on this socket, or disables it if an 337 // * empty set of parameters are provided. 338 // * 339 // * <p>This method needs to be invoked before the handshake starts. 340 // * 341 // * <p>Token binding is currently an Internet Draft that's subject to change, so the 342 // * current implementation may not be compatible with future changes in the protocol. 343 // * 344 // * @param params a list of Token Binding key parameters in descending order of preference, 345 // * as described in draft-ietf-tokbind-negotiation-09. 346 // * @throws IllegalStateException if the handshake has already started. 347 // * @throws SSLException if the setting could not be applied. 348 // */ 349 // @ExperimentalApi 350 // static void setTokenBindingParams(SSLSocket socket, int... params) { 351 // toConscrypt(socket).setTokenBindingParams(params); 352 // } 353 354 // /** 355 // * Returns the token binding parameters that were negotiated during the handshake, or -1 if 356 // * token binding parameters were not negotiated, the handshake has not yet completed, 357 // * or the connection has been closed. 358 // */ 359 // @ExperimentalApi 360 // static int getTokenBindingParams(SSLSocket socket) { 361 // return toConscrypt(socket).getTokenBindingParams(); 362 // } 363 364 // /** 365 // * Exports a value derived from the TLS master secret as described in RFC 5705. 366 // * 367 // * @param label the label to use in calculating the exported value. This must be 368 // * an ASCII-only string. 369 // * @param context the application-specific context value to use in calculating the 370 // * exported value. This may be {@code null} to use no application context, which is 371 // * treated differently than an empty byte array. 372 // * @param length the number of bytes of keying material to return. 373 // * @return a value of the specified length, or {@code null} if the handshake has not yet 374 // * completed or the connection has been closed. 375 // * @throws SSLException if the value could not be exported. 376 // */ 377 // static byte[] exportKeyingMaterial(SSLSocket socket, string label, byte[] context, 378 // int length) { 379 // return toConscrypt(socket).exportKeyingMaterial(label, context, length); 380 // } 381 382 /** 383 * Indicates whether the given {@link SSLEngine} was created by this distribution of Conscrypt. 384 */ 385 static bool isConscrypt(SSLEngine engine) { 386 AbstractConscryptEngine e = cast(AbstractConscryptEngine)engine; 387 return e !is null; 388 // return typeid(engine) == typeid(AbstractConscryptEngine); 389 } 390 391 private static AbstractConscryptEngine toConscrypt(SSLEngine engine) { 392 if (!isConscrypt(engine)) { 393 throw new IllegalArgumentException( 394 "Not a conscrypt engine: " ~ typeid(engine).name); 395 } 396 return cast(AbstractConscryptEngine) engine; 397 } 398 399 // /** 400 // * Provides the given engine with the provided bufferAllocator. 401 // */ 402 // @ExperimentalApi 403 // static void setBufferAllocator(SSLEngine engine, BufferAllocator bufferAllocator) { 404 // toConscrypt(engine).setBufferAllocator(bufferAllocator); 405 // } 406 407 // /** 408 // * Configures the default {@link BufferAllocator} to be used by all future 409 // * {@link SSLEngine} instances from this provider. 410 // */ 411 // @ExperimentalApi 412 // static void setDefaultBufferAllocator(BufferAllocator bufferAllocator) { 413 // ConscryptEngine.setDefaultBufferAllocator(bufferAllocator); 414 // } 415 416 // /** 417 // * This method enables Server Name Indication (SNI) and overrides the hostname supplied 418 // * during engine creation. 419 // * 420 // * @param engine the engine 421 // * @param hostname the desired SNI hostname, or {@code null} to disable 422 // */ 423 // static void setHostname(SSLEngine engine, string hostname) { 424 // toConscrypt(engine).setHostname(hostname); 425 // } 426 427 // /** 428 // * Returns either the hostname supplied during socket creation or via 429 // * {@link #setHostname(SSLEngine, string)}. No DNS resolution is attempted before 430 // * returning the hostname. 431 // */ 432 // static string getHostname(SSLEngine engine) { 433 // return toConscrypt(engine).getHostname(); 434 // } 435 436 // /** 437 // * Returns the maximum overhead, in bytes, of sealing a record with SSL. 438 // */ 439 // static int maxSealOverhead(SSLEngine engine) { 440 // return toConscrypt(engine).maxSealOverhead(); 441 // } 442 443 /** 444 * Sets a listener on the given engine for completion of the TLS handshake 445 */ 446 static void setHandshakeListener(SSLEngine engine, HandshakeListener handshakeListener) { 447 toConscrypt(engine).setHandshakeListener(handshakeListener); 448 } 449 450 // /** 451 // * Enables/disables TLS Channel ID for the given server-side engine. 452 // * 453 // * <p>This method needs to be invoked before the handshake starts. 454 // * 455 // * @param engine the engine 456 // * @param enabled Whether to enable channel ID. 457 // * @throws IllegalStateException if this is a client engine or if the handshake has already 458 // * started. 459 // */ 460 // static void setChannelIdEnabled(SSLEngine engine, bool enabled) { 461 // toConscrypt(engine).setChannelIdEnabled(enabled); 462 // } 463 464 // /** 465 // * Gets the TLS Channel ID for the given server-side engine. Channel ID is only available 466 // * once the handshake completes. 467 // * 468 // * @param engine the engine 469 // * @return channel ID or {@code null} if not available. 470 // * @throws IllegalStateException if this is a client engine or if the handshake has not yet 471 // * completed. 472 // * @throws SSLException if channel ID is available but could not be obtained. 473 // */ 474 // static byte[] getChannelId(SSLEngine engine) { 475 // return toConscrypt(engine).getChannelId(); 476 // } 477 478 // /** 479 // * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client engine. 480 // * 481 // * <p>This method needs to be invoked before the handshake starts. 482 // * 483 // * @param engine the engine 484 // * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key 485 // * (disables TLS Channel ID). 486 // * The private key must be an Elliptic Curve (EC) key based on the NIST P-256 curve (aka 487 // * SECG secp256r1 or ANSI X9.62 prime256v1). 488 // * @throws IllegalStateException if this is a server engine or if the handshake has already 489 // * started. 490 // */ 491 // static void setChannelIdPrivateKey(SSLEngine engine, PrivateKey privateKey) { 492 // toConscrypt(engine).setChannelIdPrivateKey(privateKey); 493 // } 494 495 // /** 496 // * Extended unwrap method for multiple source and destination buffers. 497 // * 498 // * @param engine the target engine for the unwrap 499 // * @param srcs the source buffers 500 // * @param dsts the destination buffers 501 // * @return the result of the unwrap operation 502 // * @throws SSLException thrown if an SSL error occurred 503 // */ 504 // static SSLEngineResult unwrap(SSLEngine engine, final ByteBuffer[] srcs, 505 // final ByteBuffer[] dsts) { 506 // return toConscrypt(engine).unwrap(srcs, dsts); 507 // } 508 509 // /** 510 // * Exteneded unwrap method for multiple source and destination buffers. 511 // * 512 // * @param engine the target engine for the unwrap. 513 // * @param srcs the source buffers 514 // * @param srcsOffset the offset in the {@code srcs} array of the first source buffer 515 // * @param srcsLength the number of source buffers starting at {@code srcsOffset} 516 // * @param dsts the destination buffers 517 // * @param dstsOffset the offset in the {@code dsts} array of the first destination buffer 518 // * @param dstsLength the number of destination buffers starting at {@code dstsOffset} 519 // * @return the result of the unwrap operation 520 // * @throws SSLException thrown if an SSL error occurred 521 // */ 522 // static SSLEngineResult unwrap(SSLEngine engine, final ByteBuffer[] srcs, int srcsOffset, 523 // final int srcsLength, final ByteBuffer[] dsts, final int dstsOffset, 524 // final int dstsLength) { 525 // return toConscrypt(engine).unwrap( 526 // srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength); 527 // } 528 529 // /** 530 // * This method enables session ticket support. 531 // * 532 // * @param engine the engine 533 // * @param useSessionTickets True to enable session tickets 534 // */ 535 // static void setUseSessionTickets(SSLEngine engine, bool useSessionTickets) { 536 // toConscrypt(engine).setUseSessionTickets(useSessionTickets); 537 // } 538 539 // /** 540 // * Sets the application-layer protocols (ALPN) in prioritization order. 541 // * 542 // * @param engine the engine being configured 543 // * @param protocols the protocols in descending order of preference. If empty, no protocol 544 // * indications will be used. This array will be copied. 545 // * @throws IllegalArgumentException - if protocols is null, or if any element in a non-empty 546 // * array is null or an empty (zero-length) string 547 // */ 548 static void setApplicationProtocols(SSLEngine engine, string[] protocols) { 549 toConscrypt(engine).setApplicationProtocols(protocols); 550 } 551 552 /** 553 * Gets the application-layer protocols (ALPN) in prioritization order. 554 * 555 * @param engine the engine 556 * @return the protocols in descending order of preference, or an empty array if protocol 557 * indications are not being used. Always returns a new array. 558 */ 559 static string[] getApplicationProtocols(SSLEngine engine) { 560 return toConscrypt(engine).getApplicationProtocols(); 561 } 562 563 /** 564 * Sets an application-provided ALPN protocol selector. If provided, this will override 565 * the list of protocols set by {@link #setApplicationProtocols(SSLEngine, string[])}. 566 * 567 * @param engine the engine 568 * @param selector the ALPN protocol selector 569 */ 570 static void setApplicationProtocolSelector(SSLEngine engine, 571 ApplicationProtocolSelector selector) { 572 toConscrypt(engine).setApplicationProtocolSelector(selector); 573 } 574 575 /** 576 * Returns the ALPN protocol agreed upon by client and server. 577 * 578 * @param engine the engine 579 * @return the selected protocol or {@code null} if no protocol was agreed upon. 580 */ 581 static string getApplicationProtocol(SSLEngine engine) { 582 return toConscrypt(engine).getApplicationProtocol(); 583 } 584 585 // /** 586 // * Returns the tls-unique channel binding value for this connection, per RFC 5929. This 587 // * will return {@code null} if there is no such value available, such as if the handshake 588 // * has not yet completed or this connection is closed. 589 // */ 590 // static byte[] getTlsUnique(SSLEngine engine) { 591 // return toConscrypt(engine).getTlsUnique(); 592 // } 593 594 // /** 595 // * Enables token binding parameter negotiation on this engine, or disables it if an 596 // * empty set of parameters are provided. 597 // * 598 // * <p>This method needs to be invoked before the handshake starts. 599 // * 600 // * @param params a list of Token Binding key parameters in descending order of preference, 601 // * as described in draft-ietf-tokbind-negotiation-09. 602 // * @throws IllegalStateException if the handshake has already started. 603 // * @throws SSLException if the setting could not be applied. 604 // */ 605 // static void setTokenBindingParams(SSLEngine engine, int... params) { 606 // toConscrypt(engine).setTokenBindingParams(params); 607 // } 608 609 // /** 610 // * Returns the token binding parameters that were negotiated during the handshake, or -1 if 611 // * token binding parameters were not negotiated, the handshake has not yet completed, 612 // * or the connection has been closed. 613 // */ 614 // static int getTokenBindingParams(SSLEngine engine) { 615 // return toConscrypt(engine).getTokenBindingParams(); 616 // } 617 618 // /** 619 // * Exports a value derived from the TLS master secret as described in RFC 5705. 620 // * 621 // * @param label the label to use in calculating the exported value. This must be 622 // * an ASCII-only string. 623 // * @param context the application-specific context value to use in calculating the 624 // * exported value. This may be {@code null} to use no application context, which is 625 // * treated differently than an empty byte array. 626 // * @param length the number of bytes of keying material to return. 627 // * @return a value of the specified length, or {@code null} if the handshake has not yet 628 // * completed or the connection has been closed. 629 // * @throws SSLException if the value could not be exported. 630 // */ 631 // static byte[] exportKeyingMaterial(SSLEngine engine, string label, byte[] context, 632 // int length) { 633 // return toConscrypt(engine).exportKeyingMaterial(label, context, length); 634 // } 635 }