That fuck shit the fascists are using
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.conscrypt;
17
18import java.nio.ByteBuffer;
19import java.security.KeyManagementException;
20import java.security.PrivateKey;
21import java.security.Provider;
22import java.security.cert.X509Certificate;
23import javax.net.ssl.HostnameVerifier;
24import javax.net.ssl.HttpsURLConnection;
25import javax.net.ssl.SSLContext;
26import javax.net.ssl.SSLContextSpi;
27import javax.net.ssl.SSLEngine;
28import javax.net.ssl.SSLEngineResult;
29import javax.net.ssl.SSLException;
30import javax.net.ssl.SSLServerSocketFactory;
31import javax.net.ssl.SSLSession;
32import javax.net.ssl.SSLSessionContext;
33import javax.net.ssl.SSLSocket;
34import javax.net.ssl.SSLSocketFactory;
35import javax.net.ssl.TrustManager;
36import javax.net.ssl.X509TrustManager;
37
38/**
39 * Core API for creating and configuring all Conscrypt types.
40 * This is identical to the original Conscrypt.java, except with the slow
41 * version initialization code removed.
42 */
43@SuppressWarnings("unused")
44public final class ConscryptSignal {
45 private ConscryptSignal() {}
46
47 /**
48 * Returns {@code true} if the Conscrypt native library has been successfully loaded.
49 */
50 public static boolean isAvailable() {
51 try {
52 checkAvailability();
53 return true;
54 } catch (Throwable e) {
55 return false;
56 }
57 }
58
59 // BEGIN MODIFICATION
60 /*public static class Version {
61 private final int major;
62 private final int minor;
63 private final int patch;
64
65 private Version(int major, int minor, int patch) {
66 this.major = major;
67 this.minor = minor;
68 this.patch = patch;
69 }
70
71 public int major() { return major; }
72 public int minor() { return minor; }
73 public int patch() { return patch; }
74 }
75
76 private static final Version VERSION;
77
78 static {
79 int major = -1;
80 int minor = -1;
81 int patch = -1;
82 InputStream stream = null;
83 try {
84 stream = Conscrypt.class.getResourceAsStream("conscrypt.properties");
85 if (stream != null) {
86 Properties props = new Properties();
87 props.load(stream);
88 major = Integer.parseInt(props.getProperty("org.conscrypt.version.major", "-1"));
89 minor = Integer.parseInt(props.getProperty("org.conscrypt.version.minor", "-1"));
90 patch = Integer.parseInt(props.getProperty("org.conscrypt.version.patch", "-1"));
91 }
92 } catch (IOException e) {
93 // TODO(prb): This should probably be fatal or have some fallback behaviour
94 } finally {
95 IoUtils.closeQuietly(stream);
96 }
97 if ((major >= 0) && (minor >= 0) && (patch >= 0)) {
98 VERSION = new Version(major, minor, patch);
99 } else {
100 VERSION = null;
101 }
102 }
103
104 /**
105 * Returns the version of this distribution of Conscrypt. If version information is
106 * unavailable, returns {@code null}.
107 */
108 /*public static Version version() {
109 return VERSION;
110 }*/
111
112 // END MODIFICATION
113
114 /**
115 * Checks that the Conscrypt support is available for the system.
116 *
117 * @throws UnsatisfiedLinkError if unavailable
118 */
119 public static void checkAvailability() {
120 NativeCrypto.checkAvailability();
121 }
122
123 /**
124 * Indicates whether the given {@link Provider} was created by this distribution of Conscrypt.
125 */
126 public static boolean isConscrypt(Provider provider) {
127 return provider instanceof OpenSSLProvider;
128 }
129
130 /**
131 * Constructs a new {@link Provider} with the default name.
132 */
133 public static Provider newProvider() {
134 checkAvailability();
135 return new OpenSSLProvider();
136 }
137
138 /**
139 * Constructs a new {@link Provider} with the given name.
140 *
141 * @deprecated Use {@link #newProviderBuilder()} instead.
142 */
143 @Deprecated
144 public static Provider newProvider(String providerName) {
145 checkAvailability();
146 return newProviderBuilder().setName(providerName).build();
147 }
148
149 public static class ProviderBuilder {
150 private String name = Platform.getDefaultProviderName();
151 private boolean provideTrustManager = Platform.provideTrustManagerByDefault();
152 private String defaultTlsProtocol = NativeCrypto.SUPPORTED_PROTOCOL_TLSV1_3;
153
154 private ProviderBuilder() {}
155
156 /**
157 * Sets the name of the Provider to be built.
158 */
159 public ProviderBuilder setName(String name) {
160 this.name = name;
161 return this;
162 }
163
164 /**
165 * Causes the returned provider to provide an implementation of
166 * {@link javax.net.ssl.TrustManagerFactory}.
167 * @deprecated Use provideTrustManager(true)
168 */
169 @Deprecated
170 public ProviderBuilder provideTrustManager() {
171 return provideTrustManager(true);
172 }
173
174 /**
175 * Specifies whether the returned provider will provide an implementation of
176 * {@link javax.net.ssl.TrustManagerFactory}.
177 */
178 public ProviderBuilder provideTrustManager(boolean provide) {
179 this.provideTrustManager = provide;
180 return this;
181 }
182
183 /**
184 * Specifies what the default TLS protocol should be for SSLContext identifiers
185 * {@code TLS}, {@code SSL}, and {@code Default}.
186 */
187 public ProviderBuilder defaultTlsProtocol(String defaultTlsProtocol) {
188 this.defaultTlsProtocol = defaultTlsProtocol;
189 return this;
190 }
191
192 public Provider build() {
193 return new OpenSSLProvider(name, provideTrustManager, defaultTlsProtocol);
194 }
195 }
196
197 public static ProviderBuilder newProviderBuilder() {
198 return new ProviderBuilder();
199 }
200
201 /**
202 * Returns the maximum length (in bytes) of an encrypted packet.
203 */
204 public static int maxEncryptedPacketLength() {
205 return NativeConstants.SSL3_RT_MAX_PACKET_SIZE;
206 }
207
208 /**
209 * Gets the default X.509 trust manager.
210 */
211 @ExperimentalApi
212 public static X509TrustManager getDefaultX509TrustManager() throws KeyManagementException {
213 checkAvailability();
214 return SSLParametersImpl.getDefaultX509TrustManager();
215 }
216
217 /**
218 * Indicates whether the given {@link SSLContext} was created by this distribution of Conscrypt.
219 */
220 public static boolean isConscrypt(SSLContext context) {
221 return context.getProvider() instanceof OpenSSLProvider;
222 }
223
224 /**
225 * Constructs a new instance of the preferred {@link SSLContextSpi}.
226 */
227 public static SSLContextSpi newPreferredSSLContextSpi() {
228 checkAvailability();
229 return OpenSSLContextImpl.getPreferred();
230 }
231
232 /**
233 * Sets the client-side persistent cache to be used by the context.
234 */
235 public static void setClientSessionCache(SSLContext context, SSLClientSessionCache cache) {
236 SSLSessionContext clientContext = context.getClientSessionContext();
237 if (!(clientContext instanceof ClientSessionContext)) {
238 throw new IllegalArgumentException(
239 "Not a conscrypt client context: " + clientContext.getClass().getName());
240 }
241 ((ClientSessionContext) clientContext).setPersistentCache(cache);
242 }
243
244 /**
245 * Sets the server-side persistent cache to be used by the context.
246 */
247 public static void setServerSessionCache(SSLContext context, SSLServerSessionCache cache) {
248 SSLSessionContext serverContext = context.getServerSessionContext();
249 if (!(serverContext instanceof ServerSessionContext)) {
250 throw new IllegalArgumentException(
251 "Not a conscrypt client context: " + serverContext.getClass().getName());
252 }
253 ((ServerSessionContext) serverContext).setPersistentCache(cache);
254 }
255
256 /**
257 * Indicates whether the given {@link SSLSocketFactory} was created by this distribution of
258 * Conscrypt.
259 */
260 public static boolean isConscrypt(SSLSocketFactory factory) {
261 return factory instanceof OpenSSLSocketFactoryImpl;
262 }
263
264 private static OpenSSLSocketFactoryImpl toConscrypt(SSLSocketFactory factory) {
265 if (!isConscrypt(factory)) {
266 throw new IllegalArgumentException(
267 "Not a conscrypt socket factory: " + factory.getClass().getName());
268 }
269 return (OpenSSLSocketFactoryImpl) factory;
270 }
271
272 /**
273 * Configures the default socket to be created for all socket factory instances.
274 */
275 @ExperimentalApi
276 public static void setUseEngineSocketByDefault(boolean useEngineSocket) {
277 OpenSSLSocketFactoryImpl.setUseEngineSocketByDefault(useEngineSocket);
278 OpenSSLServerSocketFactoryImpl.setUseEngineSocketByDefault(useEngineSocket);
279 }
280
281 /**
282 * Configures the socket to be created for the given socket factory instance.
283 */
284 @ExperimentalApi
285 public static void setUseEngineSocket(SSLSocketFactory factory, boolean useEngineSocket) {
286 toConscrypt(factory).setUseEngineSocket(useEngineSocket);
287 }
288
289 /**
290 * Indicates whether the given {@link SSLServerSocketFactory} was created by this distribution
291 * of Conscrypt.
292 */
293 public static boolean isConscrypt(SSLServerSocketFactory factory) {
294 return factory instanceof OpenSSLServerSocketFactoryImpl;
295 }
296
297 private static OpenSSLServerSocketFactoryImpl toConscrypt(SSLServerSocketFactory factory) {
298 if (!isConscrypt(factory)) {
299 throw new IllegalArgumentException(
300 "Not a conscrypt server socket factory: " + factory.getClass().getName());
301 }
302 return (OpenSSLServerSocketFactoryImpl) factory;
303 }
304
305 /**
306 * Configures the socket to be created for the given server socket factory instance.
307 */
308 @ExperimentalApi
309 public static void setUseEngineSocket(SSLServerSocketFactory factory, boolean useEngineSocket) {
310 toConscrypt(factory).setUseEngineSocket(useEngineSocket);
311 }
312
313 /**
314 * Indicates whether the given {@link SSLSocket} was created by this distribution of Conscrypt.
315 */
316 public static boolean isConscrypt(SSLSocket socket) {
317 return socket instanceof AbstractConscryptSocket;
318 }
319
320 private static AbstractConscryptSocket toConscrypt(SSLSocket socket) {
321 if (!isConscrypt(socket)) {
322 throw new IllegalArgumentException(
323 "Not a conscrypt socket: " + socket.getClass().getName());
324 }
325 return (AbstractConscryptSocket) socket;
326 }
327
328 /**
329 * This method enables Server Name Indication (SNI) and overrides the hostname supplied
330 * during socket creation. If the hostname is not a valid SNI hostname, the SNI extension
331 * will be omitted from the handshake.
332 *
333 * @param socket the socket
334 * @param hostname the desired SNI hostname, or null to disable
335 */
336 public static void setHostname(SSLSocket socket, String hostname) {
337 toConscrypt(socket).setHostname(hostname);
338 }
339
340 /**
341 * Returns either the hostname supplied during socket creation or via
342 * {@link #setHostname(SSLSocket, String)}. No DNS resolution is attempted before
343 * returning the hostname.
344 */
345 public static String getHostname(SSLSocket socket) {
346 return toConscrypt(socket).getHostname();
347 }
348
349 /**
350 * This method attempts to create a textual representation of the peer host or IP. Does
351 * not perform a reverse DNS lookup. This is typically used during session creation.
352 */
353 public static String getHostnameOrIP(SSLSocket socket) {
354 return toConscrypt(socket).getHostnameOrIP();
355 }
356
357 /**
358 * This method enables session ticket support.
359 *
360 * @param socket the socket
361 * @param useSessionTickets True to enable session tickets
362 */
363 public static void setUseSessionTickets(SSLSocket socket, boolean useSessionTickets) {
364 toConscrypt(socket).setUseSessionTickets(useSessionTickets);
365 }
366
367 /**
368 * Enables/disables TLS Channel ID for the given server-side socket.
369 *
370 * <p>This method needs to be invoked before the handshake starts.
371 *
372 * @param socket the socket
373 * @param enabled Whether to enable channel ID.
374 * @throws IllegalStateException if this is a client socket or if the handshake has already
375 * started.
376 */
377 public static void setChannelIdEnabled(SSLSocket socket, boolean enabled) {
378 toConscrypt(socket).setChannelIdEnabled(enabled);
379 }
380
381 /**
382 * Gets the TLS Channel ID for the given server-side socket. Channel ID is only available
383 * once the handshake completes.
384 *
385 * @param socket the socket
386 * @return channel ID or {@code null} if not available.
387 * @throws IllegalStateException if this is a client socket or if the handshake has not yet
388 * completed.
389 * @throws SSLException if channel ID is available but could not be obtained.
390 */
391 public static byte[] getChannelId(SSLSocket socket) throws SSLException {
392 return toConscrypt(socket).getChannelId();
393 }
394
395 /**
396 * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client socket.
397 *
398 * <p>This method needs to be invoked before the handshake starts.
399 *
400 * @param socket the socket
401 * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key
402 * (disables TLS Channel ID).
403 * The private key must be an Elliptic Curve (EC) key based on the NIST P-256 curve (aka
404 * SECG secp256r1 or ANSI
405 * X9.62 prime256v1).
406 * @throws IllegalStateException if this is a server socket or if the handshake has already
407 * started.
408 */
409 public static void setChannelIdPrivateKey(SSLSocket socket, PrivateKey privateKey) {
410 toConscrypt(socket).setChannelIdPrivateKey(privateKey);
411 }
412
413 /**
414 * Returns the ALPN protocol agreed upon by client and server.
415 *
416 * @param socket the socket
417 * @return the selected protocol or {@code null} if no protocol was agreed upon.
418 */
419 public static String getApplicationProtocol(SSLSocket socket) {
420 return toConscrypt(socket).getApplicationProtocol();
421 }
422
423 /**
424 * Sets an application-provided ALPN protocol selector. If provided, this will override
425 * the list of protocols set by {@link #setApplicationProtocols(SSLSocket, String[])}.
426 *
427 * @param socket the socket
428 * @param selector the ALPN protocol selector
429 */
430 public static void setApplicationProtocolSelector(SSLSocket socket,
431 ApplicationProtocolSelector selector) {
432 toConscrypt(socket).setApplicationProtocolSelector(selector);
433 }
434
435 /**
436 * Sets the application-layer protocols (ALPN) in prioritization order.
437 *
438 * @param socket the socket being configured
439 * @param protocols the protocols in descending order of preference. If empty, no protocol
440 * indications will be used. This array will be copied.
441 * @throws IllegalArgumentException - if protocols is null, or if any element in a non-empty
442 * array is null or an empty (zero-length) string
443 */
444 public static void setApplicationProtocols(SSLSocket socket, String[] protocols) {
445 toConscrypt(socket).setApplicationProtocols(protocols);
446 }
447
448 /**
449 * Gets the application-layer protocols (ALPN) in prioritization order.
450 *
451 * @param socket the socket
452 * @return the protocols in descending order of preference, or an empty array if protocol
453 * indications are not being used. Always returns a new array.
454 */
455 public static String[] getApplicationProtocols(SSLSocket socket) {
456 return toConscrypt(socket).getApplicationProtocols();
457 }
458
459 /**
460 * Returns the tls-unique channel binding value for this connection, per RFC 5929. This
461 * will return {@code null} if there is no such value available, such as if the handshake
462 * has not yet completed or this connection is closed.
463 */
464 public static byte[] getTlsUnique(SSLSocket socket) {
465 return toConscrypt(socket).getTlsUnique();
466 }
467
468 /**
469 * Exports a value derived from the TLS master secret as described in RFC 5705.
470 *
471 * @param label the label to use in calculating the exported value. This must be
472 * an ASCII-only string.
473 * @param context the application-specific context value to use in calculating the
474 * exported value. This may be {@code null} to use no application context, which is
475 * treated differently than an empty byte array.
476 * @param length the number of bytes of keying material to return.
477 * @return a value of the specified length, or {@code null} if the handshake has not yet
478 * completed or the connection has been closed.
479 * @throws SSLException if the value could not be exported.
480 */
481 public static byte[] exportKeyingMaterial(SSLSocket socket, String label, byte[] context,
482 int length) throws SSLException {
483 return toConscrypt(socket).exportKeyingMaterial(label, context, length);
484 }
485
486 /**
487 * Indicates whether the given {@link SSLEngine} was created by this distribution of Conscrypt.
488 */
489 public static boolean isConscrypt(SSLEngine engine) {
490 return engine instanceof AbstractConscryptEngine;
491 }
492
493 private static AbstractConscryptEngine toConscrypt(SSLEngine engine) {
494 if (!isConscrypt(engine)) {
495 throw new IllegalArgumentException(
496 "Not a conscrypt engine: " + engine.getClass().getName());
497 }
498 return (AbstractConscryptEngine) engine;
499 }
500
501 /**
502 * Provides the given engine with the provided bufferAllocator.
503 * @throws IllegalArgumentException if the provided engine is not a Conscrypt engine.
504 * @throws IllegalStateException if the provided engine has already begun its handshake.
505 */
506 @ExperimentalApi
507 public static void setBufferAllocator(SSLEngine engine, BufferAllocator bufferAllocator) {
508 toConscrypt(engine).setBufferAllocator(bufferAllocator);
509 }
510
511 /**
512 * Provides the given socket with the provided bufferAllocator. If the given socket is a
513 * Conscrypt socket but does not use buffer allocators, this method does nothing.
514 * @throws IllegalArgumentException if the provided socket is not a Conscrypt socket.
515 * @throws IllegalStateException if the provided socket has already begun its handshake.
516 */
517 @ExperimentalApi
518 public static void setBufferAllocator(SSLSocket socket, BufferAllocator bufferAllocator) {
519 AbstractConscryptSocket s = toConscrypt(socket);
520 if (s instanceof ConscryptEngineSocket) {
521 ((ConscryptEngineSocket) s).setBufferAllocator(bufferAllocator);
522 }
523 }
524
525 /**
526 * Configures the default {@link BufferAllocator} to be used by all future
527 * {@link SSLEngine} instances from this provider.
528 */
529 @ExperimentalApi
530 public static void setDefaultBufferAllocator(BufferAllocator bufferAllocator) {
531 ConscryptEngine.setDefaultBufferAllocator(bufferAllocator);
532 }
533
534 /**
535 * This method enables Server Name Indication (SNI) and overrides the hostname supplied
536 * during engine creation.
537 *
538 * @param engine the engine
539 * @param hostname the desired SNI hostname, or {@code null} to disable
540 */
541 public static void setHostname(SSLEngine engine, String hostname) {
542 toConscrypt(engine).setHostname(hostname);
543 }
544
545 /**
546 * Returns either the hostname supplied during socket creation or via
547 * {@link #setHostname(SSLEngine, String)}. No DNS resolution is attempted before
548 * returning the hostname.
549 */
550 public static String getHostname(SSLEngine engine) {
551 return toConscrypt(engine).getHostname();
552 }
553
554 /**
555 * Returns the maximum overhead, in bytes, of sealing a record with SSL.
556 */
557 public static int maxSealOverhead(SSLEngine engine) {
558 return toConscrypt(engine).maxSealOverhead();
559 }
560
561 /**
562 * Sets a listener on the given engine for completion of the TLS handshake
563 */
564 public static void setHandshakeListener(SSLEngine engine, HandshakeListener handshakeListener) {
565 toConscrypt(engine).setHandshakeListener(handshakeListener);
566 }
567
568 /**
569 * Enables/disables TLS Channel ID for the given server-side engine.
570 *
571 * <p>This method needs to be invoked before the handshake starts.
572 *
573 * @param engine the engine
574 * @param enabled Whether to enable channel ID.
575 * @throws IllegalStateException if this is a client engine or if the handshake has already
576 * started.
577 */
578 public static void setChannelIdEnabled(SSLEngine engine, boolean enabled) {
579 toConscrypt(engine).setChannelIdEnabled(enabled);
580 }
581
582 /**
583 * Gets the TLS Channel ID for the given server-side engine. Channel ID is only available
584 * once the handshake completes.
585 *
586 * @param engine the engine
587 * @return channel ID or {@code null} if not available.
588 * @throws IllegalStateException if this is a client engine or if the handshake has not yet
589 * completed.
590 * @throws SSLException if channel ID is available but could not be obtained.
591 */
592 public static byte[] getChannelId(SSLEngine engine) throws SSLException {
593 return toConscrypt(engine).getChannelId();
594 }
595
596 /**
597 * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client engine.
598 *
599 * <p>This method needs to be invoked before the handshake starts.
600 *
601 * @param engine the engine
602 * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key
603 * (disables TLS Channel ID).
604 * The private key must be an Elliptic Curve (EC) key based on the NIST P-256 curve (aka
605 * SECG secp256r1 or ANSI X9.62 prime256v1).
606 * @throws IllegalStateException if this is a server engine or if the handshake has already
607 * started.
608 */
609 public static void setChannelIdPrivateKey(SSLEngine engine, PrivateKey privateKey) {
610 toConscrypt(engine).setChannelIdPrivateKey(privateKey);
611 }
612
613 /**
614 * Extended unwrap method for multiple source and destination buffers.
615 *
616 * @param engine the target engine for the unwrap
617 * @param srcs the source buffers
618 * @param dsts the destination buffers
619 * @return the result of the unwrap operation
620 * @throws SSLException thrown if an SSL error occurred
621 */
622 public static SSLEngineResult unwrap(SSLEngine engine, final ByteBuffer[] srcs,
623 final ByteBuffer[] dsts) throws SSLException {
624 return toConscrypt(engine).unwrap(srcs, dsts);
625 }
626
627 /**
628 * Exteneded unwrap method for multiple source and destination buffers.
629 *
630 * @param engine the target engine for the unwrap.
631 * @param srcs the source buffers
632 * @param srcsOffset the offset in the {@code srcs} array of the first source buffer
633 * @param srcsLength the number of source buffers starting at {@code srcsOffset}
634 * @param dsts the destination buffers
635 * @param dstsOffset the offset in the {@code dsts} array of the first destination buffer
636 * @param dstsLength the number of destination buffers starting at {@code dstsOffset}
637 * @return the result of the unwrap operation
638 * @throws SSLException thrown if an SSL error occurred
639 */
640 public static SSLEngineResult unwrap(SSLEngine engine, final ByteBuffer[] srcs, int srcsOffset,
641 final int srcsLength, final ByteBuffer[] dsts, final int dstsOffset,
642 final int dstsLength) throws SSLException {
643 return toConscrypt(engine).unwrap(
644 srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
645 }
646
647 /**
648 * This method enables session ticket support.
649 *
650 * @param engine the engine
651 * @param useSessionTickets True to enable session tickets
652 */
653 public static void setUseSessionTickets(SSLEngine engine, boolean useSessionTickets) {
654 toConscrypt(engine).setUseSessionTickets(useSessionTickets);
655 }
656
657 /**
658 * Sets the application-layer protocols (ALPN) in prioritization order.
659 *
660 * @param engine the engine being configured
661 * @param protocols the protocols in descending order of preference. If empty, no protocol
662 * indications will be used. This array will be copied.
663 * @throws IllegalArgumentException - if protocols is null, or if any element in a non-empty
664 * array is null or an empty (zero-length) string
665 */
666 public static void setApplicationProtocols(SSLEngine engine, String[] protocols) {
667 toConscrypt(engine).setApplicationProtocols(protocols);
668 }
669
670 /**
671 * Gets the application-layer protocols (ALPN) in prioritization order.
672 *
673 * @param engine the engine
674 * @return the protocols in descending order of preference, or an empty array if protocol
675 * indications are not being used. Always returns a new array.
676 */
677 public static String[] getApplicationProtocols(SSLEngine engine) {
678 return toConscrypt(engine).getApplicationProtocols();
679 }
680
681 /**
682 * Sets an application-provided ALPN protocol selector. If provided, this will override
683 * the list of protocols set by {@link #setApplicationProtocols(SSLEngine, String[])}.
684 *
685 * @param engine the engine
686 * @param selector the ALPN protocol selector
687 */
688 public static void setApplicationProtocolSelector(SSLEngine engine,
689 ApplicationProtocolSelector selector) {
690 toConscrypt(engine).setApplicationProtocolSelector(selector);
691 }
692
693 /**
694 * Returns the ALPN protocol agreed upon by client and server.
695 *
696 * @param engine the engine
697 * @return the selected protocol or {@code null} if no protocol was agreed upon.
698 */
699 public static String getApplicationProtocol(SSLEngine engine) {
700 return toConscrypt(engine).getApplicationProtocol();
701 }
702
703 /**
704 * Returns the tls-unique channel binding value for this connection, per RFC 5929. This
705 * will return {@code null} if there is no such value available, such as if the handshake
706 * has not yet completed or this connection is closed.
707 */
708 public static byte[] getTlsUnique(SSLEngine engine) {
709 return toConscrypt(engine).getTlsUnique();
710 }
711
712 /**
713 * Exports a value derived from the TLS master secret as described in RFC 5705.
714 *
715 * @param label the label to use in calculating the exported value. This must be
716 * an ASCII-only string.
717 * @param context the application-specific context value to use in calculating the
718 * exported value. This may be {@code null} to use no application context, which is
719 * treated differently than an empty byte array.
720 * @param length the number of bytes of keying material to return.
721 * @return a value of the specified length, or {@code null} if the handshake has not yet
722 * completed or the connection has been closed.
723 * @throws SSLException if the value could not be exported.
724 */
725 public static byte[] exportKeyingMaterial(SSLEngine engine, String label, byte[] context,
726 int length) throws SSLException {
727 return toConscrypt(engine).exportKeyingMaterial(label, context, length);
728 }
729
730 /**
731 * Indicates whether the given {@link TrustManager} was created by this distribution of
732 * Conscrypt.
733 */
734 public static boolean isConscrypt(TrustManager trustManager) {
735 return trustManager instanceof TrustManagerImpl;
736 }
737
738 private static TrustManagerImpl toConscrypt(TrustManager trustManager) {
739 if (!isConscrypt(trustManager)) {
740 throw new IllegalArgumentException(
741 "Not a Conscrypt trust manager: " + trustManager.getClass().getName());
742 }
743 return (TrustManagerImpl) trustManager;
744 }
745
746 /**
747 * Set the default hostname verifier that will be used for HTTPS endpoint identification by
748 * Conscrypt trust managers. If {@code null} (the default), endpoint identification will use
749 * the default hostname verifier set in
750 * {@link HttpsURLConnection#setDefaultHostnameVerifier(javax.net.ssl.HostnameVerifier)}.
751 */
752 public synchronized static void setDefaultHostnameVerifier(ConscryptHostnameVerifier verifier) {
753 TrustManagerImpl.setDefaultHostnameVerifier(verifier);
754 }
755
756 /**
757 * Returns the currently-set default hostname verifier for Conscrypt trust managers.
758 *
759 * @see #setDefaultHostnameVerifier(ConscryptHostnameVerifier)
760 */
761 public synchronized static ConscryptHostnameVerifier getDefaultHostnameVerifier(TrustManager trustManager) {
762 return TrustManagerImpl.getDefaultHostnameVerifier();
763 }
764
765 /**
766 * Set the hostname verifier that will be used for HTTPS endpoint identification by the
767 * given trust manager. If {@code null} (the default), endpoint identification will use the
768 * default hostname verifier set in {@link #setDefaultHostnameVerifier(ConscryptHostnameVerifier)}.
769 *
770 * @throws IllegalArgumentException if the provided trust manager is not a Conscrypt trust
771 * manager per {@link #isConscrypt(TrustManager)}
772 */
773 public static void setHostnameVerifier(TrustManager trustManager, ConscryptHostnameVerifier verifier) {
774 toConscrypt(trustManager).setHostnameVerifier(verifier);
775 }
776
777 /**
778 * Returns the currently-set hostname verifier for the given trust manager.
779 *
780 * @throws IllegalArgumentException if the provided trust manager is not a Conscrypt trust
781 * manager per {@link #isConscrypt(TrustManager)}
782 *
783 * @see #setHostnameVerifier(TrustManager, ConscryptHostnameVerifier)
784 */
785 public static ConscryptHostnameVerifier getHostnameVerifier(TrustManager trustManager) {
786 return toConscrypt(trustManager).getHostnameVerifier();
787 }
788
789 /**
790 * Wraps the HttpsURLConnection.HostnameVerifier into a ConscryptHostnameVerifier
791 */
792 public static ConscryptHostnameVerifier wrapHostnameVerifier(final HostnameVerifier verifier) {
793 return new ConscryptHostnameVerifier() {
794 @Override
795 public boolean verify(X509Certificate[] certificates, String hostname, SSLSession session) {
796 return verifier.verify(hostname, session);
797 }
798 };
799 }
800}