1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.ssl;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.ByteBufAllocator;
20 import io.netty.handler.ssl.util.LazyJavaxX509Certificate;
21 import io.netty.handler.ssl.util.LazyX509Certificate;
22 import io.netty.internal.tcnative.AsyncTask;
23 import io.netty.internal.tcnative.Buffer;
24 import io.netty.internal.tcnative.SSL;
25 import io.netty.util.AbstractReferenceCounted;
26 import io.netty.util.CharsetUtil;
27 import io.netty.util.ReferenceCounted;
28 import io.netty.util.ResourceLeakDetector;
29 import io.netty.util.ResourceLeakDetectorFactory;
30 import io.netty.util.ResourceLeakTracker;
31 import io.netty.util.internal.EmptyArrays;
32 import io.netty.util.internal.PlatformDependent;
33 import io.netty.util.internal.StringUtil;
34 import io.netty.util.internal.ThrowableUtil;
35 import io.netty.util.internal.UnstableApi;
36 import io.netty.util.internal.logging.InternalLogger;
37 import io.netty.util.internal.logging.InternalLoggerFactory;
38
39 import java.nio.ByteBuffer;
40 import java.nio.ReadOnlyBufferException;
41 import java.security.AlgorithmConstraints;
42 import java.security.Principal;
43 import java.security.cert.Certificate;
44 import java.util.Arrays;
45 import java.util.Collection;
46 import java.util.Collections;
47 import java.util.HashSet;
48 import java.util.LinkedHashSet;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.Set;
52 import java.util.concurrent.ConcurrentHashMap;
53 import java.util.concurrent.locks.Lock;
54 import javax.crypto.spec.SecretKeySpec;
55 import javax.net.ssl.SNIHostName;
56 import javax.net.ssl.SNIMatcher;
57 import javax.net.ssl.SNIServerName;
58 import javax.net.ssl.SSLEngine;
59 import javax.net.ssl.SSLEngineResult;
60 import javax.net.ssl.SSLException;
61 import javax.net.ssl.SSLHandshakeException;
62 import javax.net.ssl.SSLParameters;
63 import javax.net.ssl.SSLPeerUnverifiedException;
64 import javax.net.ssl.SSLSession;
65 import javax.net.ssl.SSLSessionBindingEvent;
66 import javax.net.ssl.SSLSessionBindingListener;
67 import javax.security.cert.X509Certificate;
68
69 import static io.netty.handler.ssl.OpenSsl.memoryAddress;
70 import static io.netty.handler.ssl.SslUtils.SSL_RECORD_HEADER_LENGTH;
71 import static io.netty.util.internal.EmptyArrays.EMPTY_STRINGS;
72 import static io.netty.util.internal.ObjectUtil.checkNotNull;
73 import static io.netty.util.internal.ObjectUtil.checkNotNullArrayParam;
74 import static io.netty.util.internal.ObjectUtil.checkNotNullWithIAE;
75 import static java.lang.Integer.MAX_VALUE;
76 import static java.lang.Math.min;
77 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.FINISHED;
78 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_TASK;
79 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
80 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_WRAP;
81 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
82 import static javax.net.ssl.SSLEngineResult.Status.BUFFER_OVERFLOW;
83 import static javax.net.ssl.SSLEngineResult.Status.BUFFER_UNDERFLOW;
84 import static javax.net.ssl.SSLEngineResult.Status.CLOSED;
85 import static javax.net.ssl.SSLEngineResult.Status.OK;
86
87
88
89
90
91
92
93
94
95
96 public class ReferenceCountedOpenSslEngine extends SSLEngine implements ReferenceCounted, ApplicationProtocolAccessor {
97
98 private static final InternalLogger logger = InternalLoggerFactory.getInstance(ReferenceCountedOpenSslEngine.class);
99
100 private static final ResourceLeakDetector<ReferenceCountedOpenSslEngine> leakDetector =
101 ResourceLeakDetectorFactory.instance().newResourceLeakDetector(ReferenceCountedOpenSslEngine.class);
102 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2 = 0;
103 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3 = 1;
104 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1 = 2;
105 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1 = 3;
106 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2 = 4;
107 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3 = 5;
108 private static final int[] OPENSSL_OP_NO_PROTOCOLS = {
109 SSL.SSL_OP_NO_SSLv2,
110 SSL.SSL_OP_NO_SSLv3,
111 SSL.SSL_OP_NO_TLSv1,
112 SSL.SSL_OP_NO_TLSv1_1,
113 SSL.SSL_OP_NO_TLSv1_2,
114 SSL.SSL_OP_NO_TLSv1_3
115 };
116
117
118
119
120 static final int MAX_PLAINTEXT_LENGTH = SSL.SSL_MAX_PLAINTEXT_LENGTH;
121
122
123
124 static final int MAX_RECORD_SIZE = SSL.SSL_MAX_RECORD_LENGTH;
125
126 private static final SSLEngineResult NEED_UNWRAP_OK = new SSLEngineResult(OK, NEED_UNWRAP, 0, 0);
127 private static final SSLEngineResult NEED_UNWRAP_CLOSED = new SSLEngineResult(CLOSED, NEED_UNWRAP, 0, 0);
128 private static final SSLEngineResult NEED_WRAP_OK = new SSLEngineResult(OK, NEED_WRAP, 0, 0);
129 private static final SSLEngineResult NEED_WRAP_CLOSED = new SSLEngineResult(CLOSED, NEED_WRAP, 0, 0);
130 private static final SSLEngineResult CLOSED_NOT_HANDSHAKING = new SSLEngineResult(CLOSED, NOT_HANDSHAKING, 0, 0);
131
132
133 private long ssl;
134 private long networkBIO;
135
136 private enum HandshakeState {
137
138
139
140 NOT_STARTED,
141
142
143
144 STARTED_IMPLICITLY,
145
146
147
148 STARTED_EXPLICITLY,
149
150
151
152 FINISHED
153 }
154
155 private HandshakeState handshakeState = HandshakeState.NOT_STARTED;
156 private boolean receivedShutdown;
157 private volatile boolean destroyed;
158 private volatile String applicationProtocol;
159 private volatile boolean needTask;
160 private boolean hasTLSv13Cipher;
161 private boolean sessionSet;
162
163
164 private final ResourceLeakTracker<ReferenceCountedOpenSslEngine> leak;
165 private final AbstractReferenceCounted refCnt = new AbstractReferenceCounted() {
166 @Override
167 public ReferenceCounted touch(Object hint) {
168 if (leak != null) {
169 leak.record(hint);
170 }
171
172 return ReferenceCountedOpenSslEngine.this;
173 }
174
175 @Override
176 protected void deallocate() {
177 shutdown();
178 if (leak != null) {
179 boolean closed = leak.close(ReferenceCountedOpenSslEngine.this);
180 assert closed;
181 }
182 parentContext.release();
183 }
184 };
185
186 private final Set<String> enabledProtocols = new LinkedHashSet<String>();
187
188 private volatile ClientAuth clientAuth = ClientAuth.NONE;
189
190 private String endpointIdentificationAlgorithm;
191 private List<SNIServerName> serverNames;
192 private String[] groups;
193 private AlgorithmConstraints algorithmConstraints;
194
195
196 private volatile Collection<SNIMatcher> matchers;
197
198
199 private boolean isInboundDone;
200 private boolean outboundClosed;
201
202 final boolean jdkCompatibilityMode;
203 private final boolean clientMode;
204 final ByteBufAllocator alloc;
205 private final Map<Long, ReferenceCountedOpenSslEngine> engines;
206 private final OpenSslApplicationProtocolNegotiator apn;
207 private final ReferenceCountedOpenSslContext parentContext;
208 private final OpenSslInternalSession session;
209 private final ByteBuffer[] singleSrcBuffer = new ByteBuffer[1];
210 private final ByteBuffer[] singleDstBuffer = new ByteBuffer[1];
211 private final boolean enableOcsp;
212 private int maxWrapOverhead;
213 private int maxWrapBufferSize;
214 private Throwable pendingException;
215
216
217
218
219
220
221
222
223
224
225
226
227
228 ReferenceCountedOpenSslEngine(ReferenceCountedOpenSslContext context, final ByteBufAllocator alloc, String peerHost,
229 int peerPort, boolean jdkCompatibilityMode, boolean leakDetection,
230 String endpointIdentificationAlgorithm, List<SNIServerName> serverNames) {
231 super(peerHost, peerPort);
232 OpenSsl.ensureAvailability();
233 engines = context.engines;
234 enableOcsp = context.enableOcsp;
235 groups = context.groups.clone();
236 this.jdkCompatibilityMode = jdkCompatibilityMode;
237 this.alloc = checkNotNull(alloc, "alloc");
238 apn = (OpenSslApplicationProtocolNegotiator) context.applicationProtocolNegotiator();
239 clientMode = context.isClient();
240 this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
241 this.serverNames = serverNames;
242
243 session = new ExtendedOpenSslSession(new DefaultOpenSslSession(context.sessionContext())) {
244 private String[] peerSupportedSignatureAlgorithms;
245 private List<SNIServerName> requestedServerNames;
246
247 @Override
248 public List<SNIServerName> getRequestedServerNames() {
249 if (clientMode) {
250 List<SNIServerName> names = ReferenceCountedOpenSslEngine.this.serverNames;
251 return names == null ? Collections.emptyList() : Collections.unmodifiableList(names);
252 } else {
253 synchronized (ReferenceCountedOpenSslEngine.this) {
254 if (requestedServerNames == null) {
255 if (destroyed) {
256 requestedServerNames = Collections.emptyList();
257 } else {
258 String name = SSL.getSniHostname(ssl);
259 requestedServerNames = (name == null || name.isEmpty()) ?
260 Collections.emptyList() :
261
262
263 Collections.singletonList(new SNIHostName(name.getBytes(CharsetUtil.UTF_8)));
264 }
265 }
266 return requestedServerNames;
267 }
268 }
269 }
270
271 @Override
272 public String[] getPeerSupportedSignatureAlgorithms() {
273 synchronized (ReferenceCountedOpenSslEngine.this) {
274 if (peerSupportedSignatureAlgorithms == null) {
275 if (destroyed) {
276 peerSupportedSignatureAlgorithms = EMPTY_STRINGS;
277 } else {
278 String[] algs = SSL.getSigAlgs(ssl);
279 if (algs == null) {
280 peerSupportedSignatureAlgorithms = EMPTY_STRINGS;
281 } else {
282 Set<String> algorithmList = new LinkedHashSet<>(algs.length);
283 for (String alg: algs) {
284 String converted = SignatureAlgorithmConverter.toJavaName(alg);
285
286 if (converted != null) {
287 algorithmList.add(converted);
288 }
289 }
290 peerSupportedSignatureAlgorithms = algorithmList.toArray(EMPTY_STRINGS);
291 }
292 }
293 }
294 return peerSupportedSignatureAlgorithms.clone();
295 }
296 }
297
298 @Override
299 public List<byte[]> getStatusResponses() {
300 byte[] ocspResponse = null;
301 if (enableOcsp && clientMode) {
302 synchronized (ReferenceCountedOpenSslEngine.this) {
303 if (!destroyed) {
304 ocspResponse = SSL.getOcspResponse(ssl);
305 }
306 }
307 }
308 return ocspResponse == null ?
309 Collections.emptyList() : Collections.singletonList(ocspResponse);
310 }
311 };
312
313 try {
314
315
316 context.retain();
317
318 if (!context.sessionContext().useKeyManager()) {
319 session.setLocalCertificate(context.keyCertChain);
320 }
321
322 Lock readerLock = context.ctxLock.readLock();
323 readerLock.lock();
324 final long finalSsl;
325 try {
326 finalSsl = SSL.newSSL(context.ctx, !context.isClient());
327 } finally {
328 readerLock.unlock();
329 }
330 synchronized (this) {
331 ssl = finalSsl;
332 try {
333 networkBIO = SSL.bioNewByteBuffer(ssl, context.getBioNonApplicationBufferSize());
334
335
336
337 setClientAuth(clientMode ? ClientAuth.NONE : context.clientAuth);
338
339 assert context.protocols != null;
340 hasTLSv13Cipher = context.hasTLSv13Cipher;
341
342 setEnabledProtocols(context.protocols);
343
344
345
346 boolean usePeerHost = SslUtils.isValidHostNameForSNI(peerHost) && isValidHostNameForSNI(peerHost);
347 boolean useServerNames = serverNames != null && !serverNames.isEmpty();
348 if (clientMode && (usePeerHost || useServerNames)) {
349
350 if (usePeerHost) {
351 SSL.setTlsExtHostName(ssl, peerHost);
352 this.serverNames = Collections.singletonList(new SNIHostName(peerHost));
353 } else {
354 for (SNIServerName serverName : serverNames) {
355 if (serverName instanceof SNIHostName) {
356 SNIHostName name = (SNIHostName) serverName;
357 SSL.setTlsExtHostName(ssl, name.getAsciiName());
358 } else {
359 throw new IllegalArgumentException("Only " + SNIHostName.class.getName()
360 + " instances are supported, but found: " + serverName);
361 }
362 }
363 }
364 }
365
366 if (enableOcsp) {
367 SSL.enableOcsp(ssl);
368 }
369
370 if (!jdkCompatibilityMode) {
371 SSL.setMode(ssl, SSL.getMode(ssl) | SSL.SSL_MODE_ENABLE_PARTIAL_WRITE);
372 }
373
374 if (isProtocolEnabled(SSL.getOptions(ssl), SSL.SSL_OP_NO_TLSv1_3, SslProtocols.TLS_v1_3)) {
375 final boolean enableTickets = clientMode ?
376 ReferenceCountedOpenSslContext.CLIENT_ENABLE_SESSION_TICKET_TLSV13 :
377 ReferenceCountedOpenSslContext.SERVER_ENABLE_SESSION_TICKET_TLSV13;
378 if (enableTickets) {
379
380
381
382
383
384
385
386
387 SSL.clearOptions(ssl, SSL.SSL_OP_NO_TICKET);
388 }
389 }
390
391 if ((OpenSsl.isBoringSSL() || OpenSsl.isAWSLC()) && clientMode) {
392
393
394
395
396 SSL.setRenegotiateMode(ssl, SSL.SSL_RENEGOTIATE_ONCE);
397 }
398
399 calculateMaxWrapOverhead();
400
401
402 configureEndpointVerification(endpointIdentificationAlgorithm);
403 } catch (Throwable cause) {
404
405
406 shutdown();
407
408 PlatformDependent.throwException(cause);
409 }
410 }
411 } catch (Throwable cause) {
412
413
414 context.release();
415 PlatformDependent.throwException(cause);
416 }
417
418
419
420 parentContext = context;
421
422
423 engines.put(ssl, this);
424
425
426
427 leak = leakDetection ? leakDetector.track(this) : null;
428 }
429
430 private static boolean isValidHostNameForSNI(String hostname) {
431 try {
432 new SNIHostName(hostname);
433 return true;
434 } catch (IllegalArgumentException illegal) {
435 return false;
436 }
437 }
438
439 final synchronized String[] authMethods() {
440 if (destroyed) {
441 return EMPTY_STRINGS;
442 }
443 return SSL.authenticationMethods(ssl);
444 }
445
446 final void setKeyMaterial(OpenSslKeyMaterial keyMaterial) throws Exception {
447 synchronized (this) {
448 if (destroyed) {
449 return;
450 }
451 SSL.setKeyMaterial(ssl, keyMaterial.certificateChainAddress(), keyMaterial.privateKeyAddress());
452 }
453 session.setLocalCertificate(keyMaterial.certificateChain());
454 }
455
456 final synchronized SecretKeySpec masterKey() {
457 if (destroyed) {
458 return null;
459 }
460 return new SecretKeySpec(SSL.getMasterKey(ssl), "AES");
461 }
462
463 synchronized boolean isSessionReused() {
464 if (destroyed) {
465 return false;
466 }
467 return SSL.isSessionReused(ssl);
468 }
469
470
471
472
473 @UnstableApi
474 public void setOcspResponse(byte[] response) {
475 if (!enableOcsp) {
476 throw new IllegalStateException("OCSP stapling is not enabled");
477 }
478
479 if (clientMode) {
480 throw new IllegalStateException("Not a server SSLEngine");
481 }
482
483 synchronized (this) {
484 if (!destroyed) {
485 SSL.setOcspResponse(ssl, response);
486 }
487 }
488 }
489
490
491
492
493 @UnstableApi
494 public byte[] getOcspResponse() {
495 if (!enableOcsp) {
496 throw new IllegalStateException("OCSP stapling is not enabled");
497 }
498
499 if (!clientMode) {
500 throw new IllegalStateException("Not a client SSLEngine");
501 }
502
503 synchronized (this) {
504 if (destroyed) {
505 return EmptyArrays.EMPTY_BYTES;
506 }
507 return SSL.getOcspResponse(ssl);
508 }
509 }
510
511 @Override
512 public final int refCnt() {
513 return refCnt.refCnt();
514 }
515
516 @Override
517 public final ReferenceCounted retain() {
518 refCnt.retain();
519 return this;
520 }
521
522 @Override
523 public final ReferenceCounted retain(int increment) {
524 refCnt.retain(increment);
525 return this;
526 }
527
528 @Override
529 public final ReferenceCounted touch() {
530 refCnt.touch();
531 return this;
532 }
533
534 @Override
535 public final ReferenceCounted touch(Object hint) {
536 refCnt.touch(hint);
537 return this;
538 }
539
540 @Override
541 public final boolean release() {
542 return refCnt.release();
543 }
544
545 @Override
546 public final boolean release(int decrement) {
547 return refCnt.release(decrement);
548 }
549
550
551
552 public String getApplicationProtocol() {
553 return applicationProtocol;
554 }
555
556
557
558 public String getHandshakeApplicationProtocol() {
559 return applicationProtocol;
560 }
561
562 @Override
563 public final synchronized SSLSession getHandshakeSession() {
564
565
566
567
568 switch(handshakeState) {
569 case NOT_STARTED:
570 case FINISHED:
571 return null;
572 default:
573 return session;
574 }
575 }
576
577
578
579
580
581
582 public final synchronized long sslPointer() {
583 return ssl;
584 }
585
586
587
588
589 public final synchronized void shutdown() {
590 if (!destroyed) {
591 destroyed = true;
592
593
594
595 if (engines != null) {
596 engines.remove(ssl);
597 }
598 SSL.freeSSL(ssl);
599 ssl = networkBIO = 0;
600
601 isInboundDone = outboundClosed = true;
602 }
603
604
605 SSL.clearError();
606 }
607
608
609
610
611
612
613 private int writePlaintextData(final ByteBuffer src, int len) {
614 final int pos = src.position();
615 final int limit = src.limit();
616 final int sslWrote;
617
618 if (src.isDirect()) {
619 sslWrote = SSL.writeToSSL(ssl, bufferAddress(src) + pos, len);
620 if (sslWrote > 0) {
621 src.position(pos + sslWrote);
622 }
623 } else {
624 ByteBuf buf = alloc.directBuffer(len);
625 try {
626 src.limit(pos + len);
627
628 buf.setBytes(0, src);
629 src.limit(limit);
630
631 sslWrote = SSL.writeToSSL(ssl, memoryAddress(buf), len);
632 if (sslWrote > 0) {
633 src.position(pos + sslWrote);
634 } else {
635 src.position(pos);
636 }
637 } finally {
638 buf.release();
639 }
640 }
641 return sslWrote;
642 }
643
644 synchronized void bioSetFd(int fd) {
645 if (!destroyed) {
646 SSL.bioSetFd(this.ssl, fd);
647 }
648 }
649
650
651
652
653 private ByteBuf writeEncryptedData(final ByteBuffer src, int len) throws SSLException {
654 final int pos = src.position();
655 if (src.isDirect()) {
656 SSL.bioSetByteBuffer(networkBIO, bufferAddress(src) + pos, len, false);
657 } else {
658 final ByteBuf buf = alloc.directBuffer(len);
659 try {
660 final int limit = src.limit();
661 src.limit(pos + len);
662 buf.writeBytes(src);
663
664 src.position(pos);
665 src.limit(limit);
666
667 SSL.bioSetByteBuffer(networkBIO, memoryAddress(buf), len, false);
668 return buf;
669 } catch (Throwable cause) {
670 buf.release();
671 PlatformDependent.throwException(cause);
672 }
673 }
674 return null;
675 }
676
677
678
679
680 private int readPlaintextData(final ByteBuffer dst) throws SSLException {
681 final int sslRead;
682 final int pos = dst.position();
683 if (dst.isDirect()) {
684 sslRead = SSL.readFromSSL(ssl, bufferAddress(dst) + pos, dst.limit() - pos);
685 if (sslRead > 0) {
686 dst.position(pos + sslRead);
687 }
688 } else {
689 final int limit = dst.limit();
690 final int len = min(maxEncryptedPacketLength0(), limit - pos);
691 final ByteBuf buf = alloc.directBuffer(len);
692 try {
693 sslRead = SSL.readFromSSL(ssl, memoryAddress(buf), len);
694 if (sslRead > 0) {
695 dst.limit(pos + sslRead);
696 buf.getBytes(buf.readerIndex(), dst);
697 dst.limit(limit);
698 }
699 } finally {
700 buf.release();
701 }
702 }
703
704 return sslRead;
705 }
706
707
708
709
710 final synchronized int maxWrapOverhead() {
711 return maxWrapOverhead;
712 }
713
714
715
716
717 final synchronized int maxEncryptedPacketLength() {
718 return maxEncryptedPacketLength0();
719 }
720
721
722
723
724
725 final int maxEncryptedPacketLength0() {
726 return maxWrapOverhead + MAX_PLAINTEXT_LENGTH;
727 }
728
729
730
731
732
733
734
735
736
737 final int calculateMaxLengthForWrap(int plaintextLength, int numComponents) {
738 return (int) min(maxWrapBufferSize, plaintextLength + (long) maxWrapOverhead * numComponents);
739 }
740
741
742
743
744
745
746
747
748 final int calculateOutNetBufSize(int plaintextLength, int numComponents) {
749 return (int) min(MAX_VALUE, plaintextLength + (long) maxWrapOverhead * numComponents);
750 }
751
752 final synchronized int sslPending() {
753 return sslPending0();
754 }
755
756
757
758
759 private void calculateMaxWrapOverhead() {
760 maxWrapOverhead = SSL.getMaxWrapOverhead(ssl);
761
762
763
764
765 maxWrapBufferSize = jdkCompatibilityMode ? maxEncryptedPacketLength0() : maxEncryptedPacketLength0() << 4;
766 }
767
768 private int sslPending0() {
769
770
771
772
773 return handshakeState != HandshakeState.FINISHED ? 0 : SSL.sslPending(ssl);
774 }
775
776 private boolean isBytesAvailableEnoughForWrap(int bytesAvailable, int plaintextLength, int numComponents) {
777 return bytesAvailable - (long) maxWrapOverhead * numComponents >= plaintextLength;
778 }
779
780 @Override
781 public final SSLEngineResult wrap(
782 final ByteBuffer[] srcs, int offset, final int length, final ByteBuffer dst) throws SSLException {
783
784 checkNotNullWithIAE(srcs, "srcs");
785 checkNotNullWithIAE(dst, "dst");
786
787 if (offset >= srcs.length || offset + length > srcs.length) {
788 throw new IndexOutOfBoundsException(
789 "offset: " + offset + ", length: " + length +
790 " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
791 }
792
793 if (dst.isReadOnly()) {
794 throw new ReadOnlyBufferException();
795 }
796
797 synchronized (this) {
798 if (isOutboundDone()) {
799
800 return isInboundDone() || destroyed ? CLOSED_NOT_HANDSHAKING : NEED_UNWRAP_CLOSED;
801 }
802
803 int bytesProduced = 0;
804 ByteBuf bioReadCopyBuf = null;
805 try {
806
807 if (dst.isDirect()) {
808 SSL.bioSetByteBuffer(networkBIO, bufferAddress(dst) + dst.position(), dst.remaining(),
809 true);
810 } else {
811 bioReadCopyBuf = alloc.directBuffer(dst.remaining());
812 SSL.bioSetByteBuffer(networkBIO, memoryAddress(bioReadCopyBuf), bioReadCopyBuf.writableBytes(),
813 true);
814 }
815
816 int bioLengthBefore = SSL.bioLengthByteBuffer(networkBIO);
817
818
819 if (outboundClosed) {
820
821
822
823
824
825 if (!isBytesAvailableEnoughForWrap(dst.remaining(), 2, 1)) {
826 return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
827 }
828
829
830
831 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
832 if (bytesProduced <= 0) {
833 return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, 0);
834 }
835
836
837
838 if (!doSSLShutdown()) {
839 return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, bytesProduced);
840 }
841 bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
842 return newResultMayFinishHandshake(NEED_WRAP, 0, bytesProduced);
843 }
844
845
846 SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
847 HandshakeState oldHandshakeState = handshakeState;
848
849
850 if (handshakeState != HandshakeState.FINISHED) {
851 if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
852
853 handshakeState = HandshakeState.STARTED_IMPLICITLY;
854 }
855
856
857 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
858
859 if (pendingException != null) {
860
861
862
863
864
865
866
867
868
869
870
871 if (bytesProduced > 0) {
872 return newResult(NEED_WRAP, 0, bytesProduced);
873 }
874
875
876
877 return newResult(handshakeException(), 0, 0);
878 }
879
880 status = handshake();
881
882
883
884 bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
885
886 if (status == NEED_TASK) {
887 return newResult(status, 0, bytesProduced);
888 }
889
890 if (bytesProduced > 0) {
891
892
893
894 return newResult(mayFinishHandshake(status != FINISHED ?
895 bytesProduced == bioLengthBefore ? NEED_WRAP :
896 getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED),
897 0, bytesProduced);
898 }
899
900 if (status == NEED_UNWRAP) {
901
902 return isOutboundDone() ? NEED_UNWRAP_CLOSED : NEED_UNWRAP_OK;
903 }
904
905
906
907 if (outboundClosed) {
908 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
909 return newResultMayFinishHandshake(status, 0, bytesProduced);
910 }
911 }
912
913 final int endOffset = offset + length;
914 if (jdkCompatibilityMode ||
915
916
917
918 oldHandshakeState != HandshakeState.FINISHED) {
919 int srcsLen = 0;
920 for (int i = offset; i < endOffset; ++i) {
921 final ByteBuffer src = srcs[i];
922 if (src == null) {
923 throw new IllegalArgumentException("srcs[" + i + "] is null");
924 }
925 if (srcsLen == MAX_PLAINTEXT_LENGTH) {
926 continue;
927 }
928
929 srcsLen += src.remaining();
930 if (srcsLen > MAX_PLAINTEXT_LENGTH || srcsLen < 0) {
931
932
933
934 srcsLen = MAX_PLAINTEXT_LENGTH;
935 }
936 }
937
938
939
940 if (!isBytesAvailableEnoughForWrap(dst.remaining(), srcsLen, 1)) {
941 return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
942 }
943 }
944
945
946 int bytesConsumed = 0;
947 assert bytesProduced == 0;
948
949
950 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
951
952 if (bytesProduced > 0) {
953 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
954 }
955
956
957 if (pendingException != null) {
958 Throwable error = pendingException;
959 pendingException = null;
960 shutdown();
961
962
963 throw new SSLException(error);
964 }
965
966 for (; offset < endOffset; ++offset) {
967 final ByteBuffer src = srcs[offset];
968 final int remaining = src.remaining();
969 if (remaining == 0) {
970 continue;
971 }
972
973 final int bytesWritten;
974 if (jdkCompatibilityMode) {
975
976
977
978 bytesWritten = writePlaintextData(src, min(remaining, MAX_PLAINTEXT_LENGTH - bytesConsumed));
979 } else {
980
981
982
983 final int availableCapacityForWrap = dst.remaining() - bytesProduced - maxWrapOverhead;
984 if (availableCapacityForWrap <= 0) {
985 return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), bytesConsumed,
986 bytesProduced);
987 }
988 bytesWritten = writePlaintextData(src, min(remaining, availableCapacityForWrap));
989 }
990
991
992
993
994
995
996 final int pendingNow = SSL.bioLengthByteBuffer(networkBIO);
997 bytesProduced += bioLengthBefore - pendingNow;
998 bioLengthBefore = pendingNow;
999
1000 if (bytesWritten > 0) {
1001 bytesConsumed += bytesWritten;
1002
1003 if (jdkCompatibilityMode || bytesProduced == dst.remaining()) {
1004 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
1005 }
1006 } else {
1007 int sslError = SSL.getError(ssl, bytesWritten);
1008 if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
1009
1010 if (!receivedShutdown) {
1011 closeAll();
1012
1013 bytesProduced += bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
1014
1015
1016
1017
1018 SSLEngineResult.HandshakeStatus hs = mayFinishHandshake(
1019 status != FINISHED ? bytesProduced == dst.remaining() ? NEED_WRAP
1020 : getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO))
1021 : FINISHED);
1022 return newResult(hs, bytesConsumed, bytesProduced);
1023 }
1024
1025 return newResult(NOT_HANDSHAKING, bytesConsumed, bytesProduced);
1026 } else if (sslError == SSL.SSL_ERROR_WANT_READ) {
1027
1028
1029
1030 return newResult(NEED_UNWRAP, bytesConsumed, bytesProduced);
1031 } else if (sslError == SSL.SSL_ERROR_WANT_WRITE) {
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044 if (bytesProduced > 0) {
1045
1046
1047 return newResult(NEED_WRAP, bytesConsumed, bytesProduced);
1048 }
1049 return newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced);
1050 } else if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP ||
1051 sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY ||
1052 sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
1053
1054 return newResult(NEED_TASK, bytesConsumed, bytesProduced);
1055 } else {
1056
1057 throw shutdownWithError("SSL_write", sslError, SSL.getLastErrorNumber());
1058 }
1059 }
1060 }
1061 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
1062 } finally {
1063 SSL.bioClearByteBuffer(networkBIO);
1064 if (bioReadCopyBuf == null) {
1065 dst.position(dst.position() + bytesProduced);
1066 } else {
1067 assert bioReadCopyBuf.readableBytes() <= dst.remaining() : "The destination buffer " + dst +
1068 " didn't have enough remaining space to hold the encrypted content in " + bioReadCopyBuf;
1069 dst.put(bioReadCopyBuf.internalNioBuffer(bioReadCopyBuf.readerIndex(), bytesProduced));
1070 bioReadCopyBuf.release();
1071 }
1072 }
1073 }
1074 }
1075
1076 private SSLEngineResult newResult(SSLEngineResult.HandshakeStatus hs, int bytesConsumed, int bytesProduced) {
1077 return newResult(OK, hs, bytesConsumed, bytesProduced);
1078 }
1079
1080 private SSLEngineResult newResult(SSLEngineResult.Status status, SSLEngineResult.HandshakeStatus hs,
1081 int bytesConsumed, int bytesProduced) {
1082
1083
1084
1085 if (isOutboundDone()) {
1086 if (isInboundDone()) {
1087
1088 hs = NOT_HANDSHAKING;
1089
1090
1091 shutdown();
1092 }
1093 return new SSLEngineResult(CLOSED, hs, bytesConsumed, bytesProduced);
1094 }
1095 if (hs == NEED_TASK) {
1096
1097 needTask = true;
1098 }
1099 return new SSLEngineResult(status, hs, bytesConsumed, bytesProduced);
1100 }
1101
1102 private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.HandshakeStatus hs,
1103 int bytesConsumed, int bytesProduced) throws SSLException {
1104 return newResult(mayFinishHandshake(hs, bytesConsumed, bytesProduced), bytesConsumed, bytesProduced);
1105 }
1106
1107 private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.Status status,
1108 SSLEngineResult.HandshakeStatus hs,
1109 int bytesConsumed, int bytesProduced) throws SSLException {
1110 return newResult(status, mayFinishHandshake(hs, bytesConsumed, bytesProduced), bytesConsumed, bytesProduced);
1111 }
1112
1113
1114
1115
1116 private SSLException shutdownWithError(String operation, int sslError, int error) {
1117 if (logger.isDebugEnabled()) {
1118 String errorString = SSL.getErrorString(error);
1119 logger.debug("{} failed with {}: OpenSSL error: {} {}",
1120 operation, sslError, error, errorString);
1121 }
1122
1123
1124 shutdown();
1125
1126 SSLException exception = newSSLExceptionForError(error);
1127
1128 if (pendingException != null) {
1129 exception.initCause(pendingException);
1130 pendingException = null;
1131 }
1132 return exception;
1133 }
1134
1135 private SSLEngineResult handleUnwrapException(int bytesConsumed, int bytesProduced, SSLException e)
1136 throws SSLException {
1137 int lastError = SSL.getLastErrorNumber();
1138 if (lastError != 0) {
1139 return sslReadErrorResult(SSL.SSL_ERROR_SSL, lastError, bytesConsumed,
1140 bytesProduced);
1141 }
1142 throw e;
1143 }
1144
1145 public final SSLEngineResult unwrap(
1146 final ByteBuffer[] srcs, int srcsOffset, final int srcsLength,
1147 final ByteBuffer[] dsts, int dstsOffset, final int dstsLength) throws SSLException {
1148
1149
1150 checkNotNullWithIAE(srcs, "srcs");
1151 if (srcsOffset >= srcs.length
1152 || srcsOffset + srcsLength > srcs.length) {
1153 throw new IndexOutOfBoundsException(
1154 "offset: " + srcsOffset + ", length: " + srcsLength +
1155 " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
1156 }
1157 checkNotNullWithIAE(dsts, "dsts");
1158 if (dstsOffset >= dsts.length || dstsOffset + dstsLength > dsts.length) {
1159 throw new IndexOutOfBoundsException(
1160 "offset: " + dstsOffset + ", length: " + dstsLength +
1161 " (expected: offset <= offset + length <= dsts.length (" + dsts.length + "))");
1162 }
1163 long capacity = 0;
1164 final int dstsEndOffset = dstsOffset + dstsLength;
1165 for (int i = dstsOffset; i < dstsEndOffset; i ++) {
1166 ByteBuffer dst = checkNotNullArrayParam(dsts[i], i, "dsts");
1167 if (dst.isReadOnly()) {
1168 throw new ReadOnlyBufferException();
1169 }
1170 capacity += dst.remaining();
1171 }
1172
1173 final int srcsEndOffset = srcsOffset + srcsLength;
1174 long len = 0;
1175 for (int i = srcsOffset; i < srcsEndOffset; i++) {
1176 ByteBuffer src = checkNotNullArrayParam(srcs[i], i, "srcs");
1177 len += src.remaining();
1178 }
1179
1180 synchronized (this) {
1181 if (isInboundDone()) {
1182 return isOutboundDone() || destroyed ? CLOSED_NOT_HANDSHAKING : NEED_WRAP_CLOSED;
1183 }
1184
1185 SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
1186 HandshakeState oldHandshakeState = handshakeState;
1187
1188 if (handshakeState != HandshakeState.FINISHED) {
1189 if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
1190
1191 handshakeState = HandshakeState.STARTED_IMPLICITLY;
1192 }
1193
1194 status = handshake();
1195
1196 if (status == NEED_TASK) {
1197 return newResult(status, 0, 0);
1198 }
1199
1200 if (status == NEED_WRAP) {
1201 return NEED_WRAP_OK;
1202 }
1203
1204 if (isInboundDone) {
1205 return NEED_WRAP_CLOSED;
1206 }
1207 }
1208
1209 int sslPending = sslPending0();
1210 int packetLength;
1211
1212
1213
1214
1215 if (jdkCompatibilityMode ||
1216
1217
1218
1219 oldHandshakeState != HandshakeState.FINISHED) {
1220 if (len < SSL_RECORD_HEADER_LENGTH) {
1221 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
1222 }
1223
1224 packetLength = SslUtils.getEncryptedPacketLength(srcs, srcsOffset);
1225 if (packetLength == SslUtils.NOT_ENCRYPTED) {
1226 throw new NotSslRecordException("not an SSL/TLS record");
1227 }
1228
1229 assert packetLength >= 0;
1230
1231 final int packetLengthDataOnly = packetLength - SSL_RECORD_HEADER_LENGTH;
1232 if (packetLengthDataOnly > capacity) {
1233
1234
1235 if (packetLengthDataOnly > MAX_RECORD_SIZE) {
1236
1237
1238
1239
1240
1241 throw new SSLException("Illegal packet length: " + packetLengthDataOnly + " > " +
1242 session.getApplicationBufferSize());
1243 } else {
1244 session.tryExpandApplicationBufferSize(packetLengthDataOnly);
1245 }
1246 return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
1247 }
1248
1249 if (len < packetLength) {
1250
1251
1252 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
1253 }
1254 } else if (len == 0 && sslPending <= 0) {
1255 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
1256 } else if (capacity == 0) {
1257 return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
1258 } else {
1259 packetLength = (int) min(MAX_VALUE, len);
1260 }
1261
1262
1263 assert srcsOffset < srcsEndOffset;
1264
1265
1266 assert capacity > 0;
1267
1268
1269 int bytesProduced = 0;
1270 int bytesConsumed = 0;
1271 try {
1272 srcLoop:
1273 for (;;) {
1274 ByteBuffer src = srcs[srcsOffset];
1275 int remaining = src.remaining();
1276 final ByteBuf bioWriteCopyBuf;
1277 int pendingEncryptedBytes;
1278 if (remaining == 0) {
1279 if (sslPending <= 0) {
1280
1281
1282 if (++srcsOffset >= srcsEndOffset) {
1283 break;
1284 }
1285 continue;
1286 } else {
1287 bioWriteCopyBuf = null;
1288 pendingEncryptedBytes = SSL.bioLengthByteBuffer(networkBIO);
1289 }
1290 } else {
1291
1292
1293 pendingEncryptedBytes = min(packetLength, remaining);
1294 try {
1295 bioWriteCopyBuf = writeEncryptedData(src, pendingEncryptedBytes);
1296 } catch (SSLException e) {
1297
1298 return handleUnwrapException(bytesConsumed, bytesProduced, e);
1299 }
1300 }
1301 try {
1302 for (;;) {
1303 ByteBuffer dst = dsts[dstsOffset];
1304 if (!dst.hasRemaining()) {
1305
1306 if (++dstsOffset >= dstsEndOffset) {
1307 break srcLoop;
1308 }
1309 continue;
1310 }
1311
1312 int bytesRead;
1313 try {
1314 bytesRead = readPlaintextData(dst);
1315 } catch (SSLException e) {
1316
1317 return handleUnwrapException(bytesConsumed, bytesProduced, e);
1318 }
1319
1320
1321
1322 int localBytesConsumed = pendingEncryptedBytes - SSL.bioLengthByteBuffer(networkBIO);
1323 bytesConsumed += localBytesConsumed;
1324 packetLength -= localBytesConsumed;
1325 pendingEncryptedBytes -= localBytesConsumed;
1326 src.position(src.position() + localBytesConsumed);
1327
1328 if (bytesRead > 0) {
1329 bytesProduced += bytesRead;
1330
1331 if (!dst.hasRemaining()) {
1332 sslPending = sslPending0();
1333
1334 if (++dstsOffset >= dstsEndOffset) {
1335 return sslPending > 0 ?
1336 newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced) :
1337 newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1338 bytesConsumed, bytesProduced);
1339 }
1340 } else if (packetLength == 0 || jdkCompatibilityMode) {
1341
1342
1343 break srcLoop;
1344 }
1345 } else {
1346 int sslError = SSL.getError(ssl, bytesRead);
1347 if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
1348
1349
1350 break;
1351 } else if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
1352
1353 if (!receivedShutdown) {
1354 closeAll();
1355 }
1356 return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1357 bytesConsumed, bytesProduced);
1358 } else if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP ||
1359 sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY ||
1360 sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
1361 return newResult(isInboundDone() ? CLOSED : OK,
1362 NEED_TASK, bytesConsumed, bytesProduced);
1363 } else {
1364 return sslReadErrorResult(sslError, SSL.getLastErrorNumber(), bytesConsumed,
1365 bytesProduced);
1366 }
1367 }
1368 }
1369
1370 if (++srcsOffset >= srcsEndOffset) {
1371 break;
1372 }
1373 } finally {
1374 if (bioWriteCopyBuf != null) {
1375 bioWriteCopyBuf.release();
1376 }
1377 }
1378 }
1379 } finally {
1380 SSL.bioClearByteBuffer(networkBIO);
1381 rejectRemoteInitiatedRenegotiation();
1382 }
1383
1384
1385 if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) {
1386 closeAll();
1387 }
1388
1389 return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, bytesConsumed, bytesProduced);
1390 }
1391 }
1392
1393 private boolean needWrapAgain(int stackError) {
1394
1395
1396
1397
1398 if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1399
1400
1401 if (pendingException == null) {
1402 pendingException = newSSLExceptionForError(stackError);
1403 } else if (shouldAddSuppressed(pendingException, stackError)) {
1404 ThrowableUtil.addSuppressed(pendingException, newSSLExceptionForError(stackError));
1405 }
1406
1407
1408 SSL.clearError();
1409 return true;
1410 }
1411 return false;
1412 }
1413
1414 private SSLException newSSLExceptionForError(int stackError) {
1415 String message = SSL.getErrorString(stackError);
1416 return handshakeState == HandshakeState.FINISHED ?
1417 new OpenSslException(message, stackError) : new OpenSslHandshakeException(message, stackError);
1418 }
1419
1420 private static boolean shouldAddSuppressed(Throwable target, int errorCode) {
1421 for (Throwable suppressed: ThrowableUtil.getSuppressed(target)) {
1422 if (suppressed instanceof NativeSslException &&
1423 ((NativeSslException) suppressed).errorCode() == errorCode) {
1424
1425 return false;
1426 }
1427 }
1428 return true;
1429 }
1430
1431 private SSLEngineResult sslReadErrorResult(int error, int stackError, int bytesConsumed, int bytesProduced)
1432 throws SSLException {
1433 if (needWrapAgain(stackError)) {
1434
1435
1436 return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced);
1437 }
1438 throw shutdownWithError("SSL_read", error, stackError);
1439 }
1440
1441 private void closeAll() throws SSLException {
1442 receivedShutdown = true;
1443 closeOutbound();
1444 closeInbound();
1445 }
1446
1447 private void rejectRemoteInitiatedRenegotiation() throws SSLHandshakeException {
1448
1449
1450 if (destroyed || handshakeState != HandshakeState.FINISHED
1451 || SslProtocols.TLS_v1_3.equals(session.getProtocol())) {
1452 return;
1453 }
1454
1455 int count = SSL.getHandshakeCount(ssl);
1456 boolean renegotiationAttempted = (!clientMode && count > 1) || (clientMode && count > 2);
1457 if (renegotiationAttempted) {
1458 shutdown();
1459 throw new SSLHandshakeException("remote-initiated renegotiation not allowed");
1460 }
1461 }
1462
1463 public final SSLEngineResult unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts) throws SSLException {
1464 return unwrap(srcs, 0, srcs.length, dsts, 0, dsts.length);
1465 }
1466
1467 private ByteBuffer[] singleSrcBuffer(ByteBuffer src) {
1468 singleSrcBuffer[0] = src;
1469 return singleSrcBuffer;
1470 }
1471
1472 private void resetSingleSrcBuffer() {
1473 singleSrcBuffer[0] = null;
1474 }
1475
1476 private ByteBuffer[] singleDstBuffer(ByteBuffer src) {
1477 singleDstBuffer[0] = src;
1478 return singleDstBuffer;
1479 }
1480
1481 private void resetSingleDstBuffer() {
1482 singleDstBuffer[0] = null;
1483 }
1484
1485 @Override
1486 public final synchronized SSLEngineResult unwrap(
1487 final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException {
1488 try {
1489 return unwrap(singleSrcBuffer(src), 0, 1, dsts, offset, length);
1490 } finally {
1491 resetSingleSrcBuffer();
1492 }
1493 }
1494
1495 @Override
1496 public final synchronized SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1497 try {
1498 return wrap(singleSrcBuffer(src), dst);
1499 } finally {
1500 resetSingleSrcBuffer();
1501 }
1502 }
1503
1504 @Override
1505 public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1506 try {
1507 return unwrap(singleSrcBuffer(src), singleDstBuffer(dst));
1508 } finally {
1509 resetSingleSrcBuffer();
1510 resetSingleDstBuffer();
1511 }
1512 }
1513
1514 @Override
1515 public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException {
1516 try {
1517 return unwrap(singleSrcBuffer(src), dsts);
1518 } finally {
1519 resetSingleSrcBuffer();
1520 }
1521 }
1522
1523 private final class AsyncTaskDecorator implements AsyncRunnable, Runnable {
1524
1525 private final AsyncTask task;
1526
1527 AsyncTaskDecorator(AsyncTask task) {
1528 this.task = task;
1529 }
1530
1531 @Override
1532 public void run(final Runnable runnable) {
1533 if (destroyed) {
1534
1535 return;
1536 }
1537 task.runAsync(() -> runAndResetNeedTask(runnable));
1538 }
1539
1540 @Override
1541 public void run() {
1542 runAndResetNeedTask(task);
1543 }
1544 }
1545
1546 private void runAndResetNeedTask(Runnable task) {
1547
1548
1549 synchronized (ReferenceCountedOpenSslEngine.this) {
1550 try {
1551 if (destroyed) {
1552
1553 return;
1554 }
1555 task.run();
1556 if (handshakeState != HandshakeState.FINISHED && !destroyed) {
1557
1558
1559
1560 if (SSL.doHandshake(ssl) <= 0) {
1561 SSL.clearError();
1562 }
1563 }
1564 } finally {
1565
1566 needTask = false;
1567 }
1568 }
1569 }
1570
1571 @Override
1572 public final synchronized Runnable getDelegatedTask() {
1573 if (destroyed) {
1574 return null;
1575 }
1576 final Runnable task = SSL.getTask(ssl);
1577 if (task == null) {
1578 return null;
1579 }
1580 if (task instanceof AsyncTask) {
1581 return new AsyncTaskDecorator((AsyncTask) task);
1582 }
1583 return () -> runAndResetNeedTask(task);
1584 }
1585
1586 @Override
1587 public final synchronized void closeInbound() throws SSLException {
1588 if (isInboundDone) {
1589 return;
1590 }
1591
1592 isInboundDone = true;
1593
1594 if (isOutboundDone()) {
1595
1596
1597 shutdown();
1598 }
1599
1600 if (handshakeState != HandshakeState.NOT_STARTED && !receivedShutdown) {
1601 throw new SSLException(
1602 "Inbound closed before receiving peer's close_notify: possible truncation attack?");
1603 }
1604 }
1605
1606 @Override
1607 public final synchronized boolean isInboundDone() {
1608 return isInboundDone;
1609 }
1610
1611 @Override
1612 public final synchronized void closeOutbound() {
1613 if (outboundClosed) {
1614 return;
1615 }
1616
1617 outboundClosed = true;
1618
1619 if (handshakeState != HandshakeState.NOT_STARTED && !destroyed) {
1620 int mode = SSL.getShutdown(ssl);
1621 if ((mode & SSL.SSL_SENT_SHUTDOWN) != SSL.SSL_SENT_SHUTDOWN) {
1622 doSSLShutdown();
1623 }
1624 } else {
1625
1626 shutdown();
1627 }
1628 }
1629
1630
1631
1632
1633
1634 private boolean doSSLShutdown() {
1635 if (SSL.isInInit(ssl) != 0) {
1636
1637
1638
1639
1640 return false;
1641 }
1642 int err = SSL.shutdownSSL(ssl);
1643 if (err < 0) {
1644 int sslErr = SSL.getError(ssl, err);
1645 if (sslErr == SSL.SSL_ERROR_SYSCALL || sslErr == SSL.SSL_ERROR_SSL) {
1646 if (logger.isDebugEnabled()) {
1647 int error = SSL.getLastErrorNumber();
1648 logger.debug("SSL_shutdown failed: OpenSSL error: {} {}", error, SSL.getErrorString(error));
1649 }
1650
1651 shutdown();
1652 return false;
1653 }
1654 SSL.clearError();
1655 }
1656 return true;
1657 }
1658
1659 @Override
1660 public final synchronized boolean isOutboundDone() {
1661
1662
1663 return outboundClosed && (networkBIO == 0 || SSL.bioLengthNonApplication(networkBIO) == 0);
1664 }
1665
1666 @Override
1667 public final String[] getSupportedCipherSuites() {
1668 return OpenSsl.AVAILABLE_CIPHER_SUITES.toArray(EMPTY_STRINGS);
1669 }
1670
1671 @Override
1672 public final String[] getEnabledCipherSuites() {
1673 final String[] extraCiphers;
1674 final String[] enabled;
1675 final boolean tls13Enabled;
1676 synchronized (this) {
1677 if (!destroyed) {
1678 enabled = SSL.getCiphers(ssl);
1679 int opts = SSL.getOptions(ssl);
1680 if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_3, SslProtocols.TLS_v1_3)) {
1681 extraCiphers = OpenSsl.EXTRA_SUPPORTED_TLS_1_3_CIPHERS;
1682 tls13Enabled = true;
1683 } else {
1684 extraCiphers = EMPTY_STRINGS;
1685 tls13Enabled = false;
1686 }
1687 } else {
1688 return EMPTY_STRINGS;
1689 }
1690 }
1691 if (enabled == null) {
1692 return EMPTY_STRINGS;
1693 } else {
1694 Set<String> enabledSet = new LinkedHashSet<>(enabled.length + extraCiphers.length);
1695 synchronized (this) {
1696 for (String enabledCipher : enabled) {
1697 String mapped = toJavaCipherSuite(enabledCipher);
1698 final String cipher = mapped == null ? enabledCipher : mapped;
1699 if ((!tls13Enabled || !OpenSsl.isTlsv13Supported()) && SslUtils.isTLSv13Cipher(cipher)) {
1700 continue;
1701 }
1702 enabledSet.add(cipher);
1703 }
1704 Collections.addAll(enabledSet, extraCiphers);
1705 }
1706 return enabledSet.toArray(EMPTY_STRINGS);
1707 }
1708 }
1709
1710 @Override
1711 public final void setEnabledCipherSuites(String[] cipherSuites) {
1712 checkNotNull(cipherSuites, "cipherSuites");
1713
1714 final StringBuilder buf = new StringBuilder();
1715 final StringBuilder bufTLSv13 = new StringBuilder();
1716
1717 CipherSuiteConverter.convertToCipherStrings(Arrays.asList(cipherSuites), buf, bufTLSv13,
1718 OpenSsl.isBoringSSL());
1719 final String cipherSuiteSpec = buf.toString();
1720 final String cipherSuiteSpecTLSv13 = bufTLSv13.toString();
1721
1722 if (!OpenSsl.isTlsv13Supported() && !cipherSuiteSpecTLSv13.isEmpty()) {
1723 throw new IllegalArgumentException("TLSv1.3 is not supported by this java version.");
1724 }
1725 synchronized (this) {
1726 hasTLSv13Cipher = !cipherSuiteSpecTLSv13.isEmpty();
1727 if (!destroyed) {
1728 try {
1729
1730 SSL.setCipherSuites(ssl, cipherSuiteSpec, false);
1731 if (OpenSsl.isTlsv13Supported()) {
1732
1733 SSL.setCipherSuites(ssl, OpenSsl.checkTls13Ciphers(logger, cipherSuiteSpecTLSv13), true);
1734 }
1735
1736
1737
1738 Set<String> protocols = new HashSet<String>(enabledProtocols);
1739
1740
1741
1742 if (cipherSuiteSpec.isEmpty()) {
1743 protocols.remove(SslProtocols.TLS_v1);
1744 protocols.remove(SslProtocols.TLS_v1_1);
1745 protocols.remove(SslProtocols.TLS_v1_2);
1746 protocols.remove(SslProtocols.SSL_v3);
1747 protocols.remove(SslProtocols.SSL_v2);
1748 protocols.remove(SslProtocols.SSL_v2_HELLO);
1749 }
1750
1751 if (cipherSuiteSpecTLSv13.isEmpty()) {
1752 protocols.remove(SslProtocols.TLS_v1_3);
1753 }
1754
1755
1756 setEnabledProtocols0(protocols.toArray(EMPTY_STRINGS), !hasTLSv13Cipher);
1757 } catch (Exception e) {
1758 throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec, e);
1759 }
1760 } else {
1761 throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec);
1762 }
1763 }
1764 }
1765
1766 @Override
1767 public final String[] getSupportedProtocols() {
1768 return OpenSsl.unpackSupportedProtocols().toArray(EMPTY_STRINGS);
1769 }
1770
1771 @Override
1772 public final String[] getEnabledProtocols() {
1773 return enabledProtocols.toArray(EMPTY_STRINGS);
1774 }
1775
1776 private static boolean isProtocolEnabled(int opts, int disableMask, String protocolString) {
1777
1778
1779 return (opts & disableMask) == 0 && OpenSsl.isProtocolSupported(protocolString);
1780 }
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791 @Override
1792 public final void setEnabledProtocols(String[] protocols) {
1793 checkNotNullWithIAE(protocols, "protocols");
1794 synchronized (this) {
1795 enabledProtocols.clear();
1796
1797 enabledProtocols.add(SslProtocols.SSL_v2_HELLO);
1798
1799 Collections.addAll(enabledProtocols, protocols);
1800
1801 setEnabledProtocols0(protocols, !hasTLSv13Cipher);
1802 }
1803 }
1804
1805 private void setEnabledProtocols0(String[] protocols, boolean explicitDisableTLSv13) {
1806 assert Thread.holdsLock(this);
1807
1808 int minProtocolIndex = OPENSSL_OP_NO_PROTOCOLS.length;
1809 int maxProtocolIndex = 0;
1810 for (String protocol : protocols) {
1811 if (!OpenSsl.isProtocolSupported(protocol)) {
1812 throw new IllegalArgumentException("Protocol " + protocol + " is not supported.");
1813 }
1814
1815 int index;
1816 switch (protocol) {
1817 case SslProtocols.SSL_v2:
1818 index = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2;
1819 break;
1820 case SslProtocols.SSL_v3:
1821 index = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3;
1822 break;
1823 case SslProtocols.TLS_v1:
1824 index = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1;
1825 break;
1826 case SslProtocols.TLS_v1_1:
1827 index = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1;
1828 break;
1829 case SslProtocols.TLS_v1_2:
1830 index = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
1831 break;
1832 case SslProtocols.TLS_v1_3:
1833 if (explicitDisableTLSv13) {
1834 continue;
1835 }
1836 index = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3;
1837 break;
1838 default:
1839 continue;
1840 }
1841
1842 minProtocolIndex = Math.min(minProtocolIndex, index);
1843 maxProtocolIndex = Math.max(maxProtocolIndex, index);
1844 }
1845
1846 if (destroyed) {
1847 throw new IllegalStateException("failed to enable protocols: " + Arrays.asList(protocols));
1848 }
1849
1850 SSL.clearOptions(ssl, SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 |
1851 SSL.SSL_OP_NO_TLSv1 | SSL.SSL_OP_NO_TLSv1_1 |
1852 SSL.SSL_OP_NO_TLSv1_2 | SSL.SSL_OP_NO_TLSv1_3);
1853
1854 int opts = 0;
1855 for (int i = 0; i < minProtocolIndex; ++i) {
1856 opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1857 }
1858 assert maxProtocolIndex != MAX_VALUE;
1859 for (int i = maxProtocolIndex + 1; i < OPENSSL_OP_NO_PROTOCOLS.length; ++i) {
1860 opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1861 }
1862
1863 SSL.setOptions(ssl, opts);
1864 }
1865
1866 @Override
1867 public final SSLSession getSession() {
1868 return session;
1869 }
1870
1871 @Override
1872 public final synchronized void beginHandshake() throws SSLException {
1873 switch (handshakeState) {
1874 case STARTED_IMPLICITLY:
1875 checkEngineClosed();
1876
1877
1878
1879
1880
1881
1882
1883 handshakeState = HandshakeState.STARTED_EXPLICITLY;
1884 calculateMaxWrapOverhead();
1885
1886 break;
1887 case STARTED_EXPLICITLY:
1888
1889 break;
1890 case FINISHED:
1891 throw new SSLException("renegotiation unsupported");
1892 case NOT_STARTED:
1893 handshakeState = HandshakeState.STARTED_EXPLICITLY;
1894 if (handshake() == NEED_TASK) {
1895
1896 needTask = true;
1897 }
1898 calculateMaxWrapOverhead();
1899 break;
1900 default:
1901 throw new Error("Unexpected handshake state: " + handshakeState);
1902 }
1903 }
1904
1905 private void checkEngineClosed() throws SSLException {
1906 if (destroyed) {
1907 throw new SSLException("engine closed");
1908 }
1909 }
1910
1911 private static SSLEngineResult.HandshakeStatus pendingStatus(int pendingStatus) {
1912
1913 return pendingStatus > 0 ? NEED_WRAP : NEED_UNWRAP;
1914 }
1915
1916 private static boolean isEmpty(Object[] arr) {
1917 return arr == null || arr.length == 0;
1918 }
1919
1920 private static boolean isEmpty(byte[] cert) {
1921 return cert == null || cert.length == 0;
1922 }
1923
1924 private SSLEngineResult.HandshakeStatus handshakeException() throws SSLException {
1925 if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1926
1927 return NEED_WRAP;
1928 }
1929
1930 Throwable exception = pendingException;
1931 assert exception != null;
1932 pendingException = null;
1933 shutdown();
1934 if (exception instanceof SSLHandshakeException) {
1935 throw (SSLHandshakeException) exception;
1936 }
1937 SSLHandshakeException e = new SSLHandshakeException("General OpenSslEngine problem");
1938 e.initCause(exception);
1939 throw e;
1940 }
1941
1942
1943
1944
1945
1946 final void initHandshakeException(Throwable cause) {
1947 if (pendingException == null) {
1948 pendingException = cause;
1949 } else {
1950 ThrowableUtil.addSuppressed(pendingException, cause);
1951 }
1952 }
1953
1954 private SSLEngineResult.HandshakeStatus handshake() throws SSLException {
1955 if (needTask) {
1956 return NEED_TASK;
1957 }
1958 if (handshakeState == HandshakeState.FINISHED) {
1959 return FINISHED;
1960 }
1961
1962 checkEngineClosed();
1963
1964 if (pendingException != null) {
1965
1966
1967 if (SSL.doHandshake(ssl) <= 0) {
1968
1969 SSL.clearError();
1970 }
1971 return handshakeException();
1972 }
1973
1974 if (!sessionSet) {
1975 if (!parentContext.sessionContext().setSessionFromCache(ssl, session, getPeerHost(), getPeerPort())) {
1976
1977
1978 session.prepareHandshake();
1979 }
1980 sessionSet = true;
1981 }
1982
1983 int code = SSL.doHandshake(ssl);
1984 if (code <= 0) {
1985 int sslError = SSL.getError(ssl, code);
1986 if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
1987 return pendingStatus(SSL.bioLengthNonApplication(networkBIO));
1988 }
1989
1990 if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP ||
1991 sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY ||
1992 sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
1993 return NEED_TASK;
1994 }
1995
1996 int errorNumber = SSL.getLastErrorNumber();
1997 if (needWrapAgain(errorNumber)) {
1998
1999
2000 return NEED_WRAP;
2001 }
2002
2003
2004 if (pendingException != null) {
2005 return handshakeException();
2006 }
2007
2008
2009 throw shutdownWithError("SSL_do_handshake", sslError, errorNumber);
2010 }
2011
2012 if (SSL.bioLengthNonApplication(networkBIO) > 0) {
2013 return NEED_WRAP;
2014 }
2015
2016 session.handshakeFinished(SSL.getSessionId(ssl), SSL.getCipherForSSL(ssl), SSL.getVersion(ssl),
2017 SSL.getPeerCertificate(ssl), SSL.getPeerCertChain(ssl),
2018 SSL.getTime(ssl) * 1000L, parentContext.sessionTimeout() * 1000L);
2019 selectApplicationProtocol();
2020 return FINISHED;
2021 }
2022
2023 private SSLEngineResult.HandshakeStatus mayFinishHandshake(
2024 SSLEngineResult.HandshakeStatus hs, int bytesConsumed, int bytesProduced) throws SSLException {
2025 return hs == NEED_UNWRAP && bytesProduced > 0 || hs == NEED_WRAP && bytesConsumed > 0 ?
2026 handshake() : mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED);
2027 }
2028
2029 private SSLEngineResult.HandshakeStatus mayFinishHandshake(SSLEngineResult.HandshakeStatus status)
2030 throws SSLException {
2031 if (status == NOT_HANDSHAKING) {
2032 if (handshakeState != HandshakeState.FINISHED) {
2033
2034
2035 return handshake();
2036 }
2037 if (!destroyed && SSL.bioLengthNonApplication(networkBIO) > 0) {
2038
2039 return NEED_WRAP;
2040 }
2041 }
2042 return status;
2043 }
2044
2045 @Override
2046 public final synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
2047
2048 if (needPendingStatus()) {
2049 if (needTask) {
2050
2051 return NEED_TASK;
2052 }
2053 return pendingStatus(SSL.bioLengthNonApplication(networkBIO));
2054 }
2055 return NOT_HANDSHAKING;
2056 }
2057
2058 private SSLEngineResult.HandshakeStatus getHandshakeStatus(int pending) {
2059
2060 if (needPendingStatus()) {
2061 if (needTask) {
2062
2063 return NEED_TASK;
2064 }
2065 return pendingStatus(pending);
2066 }
2067 return NOT_HANDSHAKING;
2068 }
2069
2070 private boolean needPendingStatus() {
2071 return handshakeState != HandshakeState.NOT_STARTED && !destroyed
2072 && (handshakeState != HandshakeState.FINISHED || isInboundDone() || isOutboundDone());
2073 }
2074
2075
2076
2077
2078 private String toJavaCipherSuite(String openSslCipherSuite) {
2079 if (openSslCipherSuite == null) {
2080 return null;
2081 }
2082
2083 String version = SSL.getVersion(ssl);
2084 return toJavaCipherSuite(openSslCipherSuite, version);
2085 }
2086
2087 private String toJavaCipherSuite(String openSslCipherSuite, String version) {
2088 if (openSslCipherSuite == null) {
2089 return null;
2090 }
2091 String prefix = toJavaCipherSuitePrefix(version);
2092 return CipherSuiteConverter.toJava(openSslCipherSuite, prefix);
2093 }
2094
2095
2096
2097
2098 private static String toJavaCipherSuitePrefix(String protocolVersion) {
2099 final char c;
2100 if (protocolVersion == null || protocolVersion.isEmpty()) {
2101 c = 0;
2102 } else {
2103 c = protocolVersion.charAt(0);
2104 }
2105
2106 switch (c) {
2107 case 'T':
2108 return "TLS";
2109 case 'S':
2110 return "SSL";
2111 default:
2112 return "UNKNOWN";
2113 }
2114 }
2115
2116 @Override
2117 public final void setUseClientMode(boolean clientMode) {
2118 if (clientMode != this.clientMode) {
2119 throw new UnsupportedOperationException();
2120 }
2121 }
2122
2123 @Override
2124 public final boolean getUseClientMode() {
2125 return clientMode;
2126 }
2127
2128 @Override
2129 public final void setNeedClientAuth(boolean b) {
2130 setClientAuth(b ? ClientAuth.REQUIRE : ClientAuth.NONE);
2131 }
2132
2133 @Override
2134 public final boolean getNeedClientAuth() {
2135 return clientAuth == ClientAuth.REQUIRE;
2136 }
2137
2138 @Override
2139 public final void setWantClientAuth(boolean b) {
2140 setClientAuth(b ? ClientAuth.OPTIONAL : ClientAuth.NONE);
2141 }
2142
2143 @Override
2144 public final boolean getWantClientAuth() {
2145 return clientAuth == ClientAuth.OPTIONAL;
2146 }
2147
2148
2149
2150
2151
2152 @UnstableApi
2153 public final synchronized void setVerify(int verifyMode, int depth) {
2154 if (!destroyed) {
2155 SSL.setVerify(ssl, verifyMode, depth);
2156 }
2157 }
2158
2159 private void setClientAuth(ClientAuth mode) {
2160 if (clientMode) {
2161 return;
2162 }
2163 synchronized (this) {
2164 if (clientAuth == mode) {
2165
2166 return;
2167 }
2168 if (!destroyed) {
2169 switch (mode) {
2170 case NONE:
2171 SSL.setVerify(ssl, SSL.SSL_CVERIFY_NONE, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
2172 break;
2173 case REQUIRE:
2174 SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
2175 break;
2176 case OPTIONAL:
2177 SSL.setVerify(ssl, SSL.SSL_CVERIFY_OPTIONAL, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
2178 break;
2179 default:
2180 throw new Error("Unexpected client auth mode: " + mode);
2181 }
2182 }
2183 clientAuth = mode;
2184 }
2185 }
2186
2187 @Override
2188 public final void setEnableSessionCreation(boolean b) {
2189 if (b) {
2190 throw new UnsupportedOperationException();
2191 }
2192 }
2193
2194 @Override
2195 public final boolean getEnableSessionCreation() {
2196 return false;
2197 }
2198
2199 @Override
2200 public final synchronized SSLParameters getSSLParameters() {
2201 SSLParameters sslParameters = super.getSSLParameters();
2202
2203 sslParameters.setEndpointIdentificationAlgorithm(endpointIdentificationAlgorithm);
2204 sslParameters.setAlgorithmConstraints(algorithmConstraints);
2205 sslParameters.setServerNames(serverNames);
2206 if (groups != null) {
2207 OpenSslParametersUtil.setNamesGroups(sslParameters, groups.clone());
2208 }
2209 if (!destroyed) {
2210 sslParameters.setUseCipherSuitesOrder((SSL.getOptions(ssl) & SSL.SSL_OP_CIPHER_SERVER_PREFERENCE) != 0);
2211 }
2212
2213 sslParameters.setSNIMatchers(matchers);
2214 return sslParameters;
2215 }
2216
2217 @Override
2218 public final synchronized void setSSLParameters(SSLParameters sslParameters) {
2219 if (sslParameters.getAlgorithmConstraints() != null) {
2220 throw new IllegalArgumentException("AlgorithmConstraints are not supported.");
2221 }
2222
2223 boolean isDestroyed = destroyed;
2224 if (!isDestroyed) {
2225 if (clientMode) {
2226 List<SNIServerName> proposedServerNames = sslParameters.getServerNames();
2227 if (proposedServerNames != null && !proposedServerNames.isEmpty()) {
2228 for (SNIServerName serverName : proposedServerNames) {
2229 if (!(serverName instanceof SNIHostName)) {
2230 throw new IllegalArgumentException("Only " + SNIHostName.class.getName()
2231 + " instances are supported, but found: " + serverName);
2232 }
2233 }
2234 for (SNIServerName serverName : proposedServerNames) {
2235 SNIHostName name = (SNIHostName) serverName;
2236 SSL.setTlsExtHostName(ssl, name.getAsciiName());
2237 }
2238 }
2239 serverNames = proposedServerNames;
2240 }
2241
2242 String[] groups = OpenSslParametersUtil.getNamesGroups(sslParameters);
2243 if (groups != null) {
2244 Set<String> groupsSet = new LinkedHashSet<String>(groups.length);
2245 for (String group : groups) {
2246 if (group == null || group.isEmpty()) {
2247
2248 throw new IllegalArgumentException();
2249 }
2250 if (!groupsSet.add(GroupsConverter.toOpenSsl(group))) {
2251
2252 throw new IllegalArgumentException("named groups contains a duplicate");
2253 }
2254 }
2255 if (!SSL.setCurvesList(ssl, groupsSet.toArray(EMPTY_STRINGS))) {
2256 throw new UnsupportedOperationException();
2257 }
2258 this.groups = groups;
2259 }
2260 if (sslParameters.getUseCipherSuitesOrder()) {
2261 SSL.setOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
2262 } else {
2263 SSL.clearOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
2264 }
2265 }
2266 matchers = sslParameters.getSNIMatchers();
2267
2268 final String endpointIdentificationAlgorithm = sslParameters.getEndpointIdentificationAlgorithm();
2269 if (!isDestroyed) {
2270 configureEndpointVerification(endpointIdentificationAlgorithm);
2271 }
2272 this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
2273 algorithmConstraints = sslParameters.getAlgorithmConstraints();
2274 super.setSSLParameters(sslParameters);
2275 }
2276
2277 private void configureEndpointVerification(String endpointIdentificationAlgorithm) {
2278
2279
2280 if (clientMode && isEndPointVerificationEnabled(endpointIdentificationAlgorithm)) {
2281 SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, -1);
2282 }
2283 }
2284
2285 private static boolean isEndPointVerificationEnabled(String endPointIdentificationAlgorithm) {
2286 return endPointIdentificationAlgorithm != null && !endPointIdentificationAlgorithm.isEmpty();
2287 }
2288
2289 final boolean checkSniHostnameMatch(String hostname) {
2290 Collection<SNIMatcher> matchers = this.matchers;
2291 if (matchers != null && !matchers.isEmpty()) {
2292 SNIHostName name = new SNIHostName(hostname.getBytes(CharsetUtil.UTF_8));
2293 for (SNIMatcher matcher : matchers) {
2294
2295 if (matcher.getType() == 0 && matcher.matches(name)) {
2296 return true;
2297 }
2298 }
2299 return false;
2300 }
2301 return true;
2302 }
2303
2304 @Override
2305 public String getNegotiatedApplicationProtocol() {
2306 return applicationProtocol;
2307 }
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322 public void addCredential(OpenSslCredential credential) throws SSLException {
2323 synchronized (this) {
2324 try {
2325 if (destroyed) {
2326 throw new IllegalStateException("Engine is destroyed");
2327 }
2328 if (handshakeState != HandshakeState.NOT_STARTED) {
2329 throw new IllegalStateException("Handshake has already started");
2330 }
2331 if (!(credential instanceof OpenSslCredentialPointer)) {
2332 throw new IllegalArgumentException("Unsupported credential type: " + credential);
2333 }
2334 } catch (RuntimeException re) {
2335 try {
2336 credential.release();
2337 } catch (Throwable th) {
2338 re.addSuppressed(th);
2339 }
2340 throw re;
2341 }
2342 OpenSslCredentialPointer pointer = (OpenSslCredentialPointer) credential;
2343
2344
2345
2346 credential.retain();
2347 try {
2348 SSL.addCredential(ssl, pointer.credentialAddress());
2349 } catch (Exception e) {
2350 credential.release();
2351 throw new SSLException("Failed to add credential to SSL engine", e);
2352 }
2353 }
2354 }
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368 public OpenSslCredential getSelectedCredential() throws SSLException {
2369 synchronized (this) {
2370 if (destroyed) {
2371 return null;
2372 }
2373 try {
2374 long credPtr = io.netty.internal.tcnative.SSL.getSelectedCredential(ssl);
2375 if (credPtr == 0) {
2376 return null;
2377 }
2378
2379 return new NonOwnedOpenSslCredential(credPtr, OpenSslCredential.CredentialType.X509);
2380 } catch (Exception e) {
2381 throw new SSLException("Failed to get selected credential", e);
2382 }
2383 }
2384 }
2385
2386 private static long bufferAddress(ByteBuffer b) {
2387 assert b.isDirect();
2388 if (PlatformDependent.hasUnsafe()) {
2389 return PlatformDependent.directBufferAddress(b);
2390 }
2391 return Buffer.address(b);
2392 }
2393
2394
2395
2396
2397 private void selectApplicationProtocol() throws SSLException {
2398 ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior = apn.selectedListenerFailureBehavior();
2399 List<String> protocols = apn.protocols();
2400 String applicationProtocol;
2401 switch (apn.protocol()) {
2402 case NONE:
2403 break;
2404
2405
2406 case ALPN:
2407 applicationProtocol = SSL.getAlpnSelected(ssl);
2408 if (applicationProtocol != null) {
2409 this.applicationProtocol = selectApplicationProtocol(
2410 protocols, behavior, applicationProtocol);
2411 }
2412 break;
2413 case NPN:
2414 applicationProtocol = SSL.getNextProtoNegotiated(ssl);
2415 if (applicationProtocol != null) {
2416 this.applicationProtocol = selectApplicationProtocol(
2417 protocols, behavior, applicationProtocol);
2418 }
2419 break;
2420 case NPN_AND_ALPN:
2421 applicationProtocol = SSL.getAlpnSelected(ssl);
2422 if (applicationProtocol == null) {
2423 applicationProtocol = SSL.getNextProtoNegotiated(ssl);
2424 }
2425 if (applicationProtocol != null) {
2426 this.applicationProtocol = selectApplicationProtocol(
2427 protocols, behavior, applicationProtocol);
2428 }
2429 break;
2430 default:
2431 throw new Error("Unexpected apn protocol: " + apn.protocol());
2432 }
2433 }
2434
2435 private static String selectApplicationProtocol(List<String> protocols,
2436 ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior,
2437 String applicationProtocol) throws SSLException {
2438 if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT) {
2439 return applicationProtocol;
2440 } else {
2441 int size = protocols.size();
2442 assert size > 0;
2443 if (protocols.contains(applicationProtocol)) {
2444 return applicationProtocol;
2445 } else {
2446 if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.CHOOSE_MY_LAST_PROTOCOL) {
2447 return protocols.get(size - 1);
2448 } else {
2449 throw new SSLException("unknown protocol " + applicationProtocol);
2450 }
2451 }
2452 }
2453 }
2454
2455 private static final X509Certificate[] JAVAX_CERTS_NOT_SUPPORTED = new X509Certificate[0];
2456
2457 private final class DefaultOpenSslSession implements OpenSslInternalSession {
2458 private final OpenSslSessionContext sessionContext;
2459
2460
2461
2462 private X509Certificate[] x509PeerCerts;
2463 private Certificate[] peerCerts;
2464
2465 private boolean valid = true;
2466 private String protocol;
2467 private String cipher;
2468 private OpenSslSessionId id = OpenSslSessionId.NULL_ID;
2469 private long creationTime;
2470
2471
2472 private long lastAccessed = -1;
2473
2474 private volatile int applicationBufferSize = MAX_PLAINTEXT_LENGTH;
2475 private volatile Certificate[] localCertificateChain;
2476 private volatile Map<String, Object> keyValueStorage = new ConcurrentHashMap<String, Object>();
2477
2478 DefaultOpenSslSession(OpenSslSessionContext sessionContext) {
2479 this.sessionContext = sessionContext;
2480 }
2481
2482 private SSLSessionBindingEvent newSSLSessionBindingEvent(String name) {
2483 return new SSLSessionBindingEvent(session, name);
2484 }
2485
2486 @Override
2487 public void prepareHandshake() {
2488 keyValueStorage.clear();
2489 }
2490
2491 @Override
2492 public void setSessionDetails(
2493 long creationTime, long lastAccessedTime, OpenSslSessionId sessionId,
2494 Map<String, Object> keyValueStorage) {
2495 synchronized (ReferenceCountedOpenSslEngine.this) {
2496 if (id == OpenSslSessionId.NULL_ID) {
2497 id = sessionId;
2498 this.creationTime = creationTime;
2499 lastAccessed = lastAccessedTime;
2500
2501
2502
2503
2504 this.keyValueStorage = keyValueStorage;
2505 }
2506 }
2507 }
2508
2509 @Override
2510 public Map<String, Object> keyValueStorage() {
2511 return keyValueStorage;
2512 }
2513
2514 @Override
2515 public OpenSslSessionId sessionId() {
2516 synchronized (ReferenceCountedOpenSslEngine.this) {
2517 if (this.id == OpenSslSessionId.NULL_ID && !destroyed) {
2518 byte[] sessionId = SSL.getSessionId(ssl);
2519 if (sessionId != null) {
2520 id = new OpenSslSessionId(sessionId);
2521 }
2522 }
2523
2524 return id;
2525 }
2526 }
2527
2528 @Override
2529 public void setLocalCertificate(Certificate[] localCertificate) {
2530 localCertificateChain = localCertificate;
2531 }
2532
2533 @Override
2534 public byte[] getId() {
2535 return sessionId().cloneBytes();
2536 }
2537
2538 @Override
2539 public OpenSslSessionContext getSessionContext() {
2540 return sessionContext;
2541 }
2542
2543 @Override
2544 public long getCreationTime() {
2545 synchronized (ReferenceCountedOpenSslEngine.this) {
2546 return creationTime;
2547 }
2548 }
2549
2550 @Override
2551 public void setLastAccessedTime(long time) {
2552 synchronized (ReferenceCountedOpenSslEngine.this) {
2553 lastAccessed = time;
2554 }
2555 }
2556
2557 @Override
2558 public long getLastAccessedTime() {
2559
2560 synchronized (ReferenceCountedOpenSslEngine.this) {
2561 return lastAccessed == -1 ? creationTime : lastAccessed;
2562 }
2563 }
2564
2565 @Override
2566 public void invalidate() {
2567 synchronized (ReferenceCountedOpenSslEngine.this) {
2568 valid = false;
2569 sessionContext.removeFromCache(id);
2570 }
2571 }
2572
2573 @Override
2574 public boolean isValid() {
2575 synchronized (ReferenceCountedOpenSslEngine.this) {
2576 return valid || sessionContext.isInCache(id);
2577 }
2578 }
2579
2580 @Override
2581 public void putValue(String name, Object value) {
2582 checkNotNull(name, "name");
2583 checkNotNull(value, "value");
2584
2585 final Object old = keyValueStorage.put(name, value);
2586 if (value instanceof SSLSessionBindingListener) {
2587
2588 ((SSLSessionBindingListener) value).valueBound(newSSLSessionBindingEvent(name));
2589 }
2590 notifyUnbound(old, name);
2591 }
2592
2593 @Override
2594 public Object getValue(String name) {
2595 checkNotNull(name, "name");
2596 return keyValueStorage.get(name);
2597 }
2598
2599 @Override
2600 public void removeValue(String name) {
2601 checkNotNull(name, "name");
2602 final Object old = keyValueStorage.remove(name);
2603 notifyUnbound(old, name);
2604 }
2605
2606 @Override
2607 public String[] getValueNames() {
2608 return keyValueStorage.keySet().toArray(EMPTY_STRINGS);
2609 }
2610
2611 private void notifyUnbound(Object value, String name) {
2612 if (value instanceof SSLSessionBindingListener) {
2613
2614 ((SSLSessionBindingListener) value).valueUnbound(newSSLSessionBindingEvent(name));
2615 }
2616 }
2617
2618
2619
2620
2621
2622 @Override
2623 public void handshakeFinished(byte[] id, String cipher, String protocol, byte[] peerCertificate,
2624 byte[][] peerCertificateChain, long creationTime, long timeout)
2625 throws SSLException {
2626 synchronized (ReferenceCountedOpenSslEngine.this) {
2627 if (!destroyed) {
2628 if (this.id == OpenSslSessionId.NULL_ID) {
2629
2630
2631 this.id = id == null ? OpenSslSessionId.NULL_ID : new OpenSslSessionId(id);
2632
2633
2634 this.creationTime = lastAccessed = creationTime;
2635 }
2636 this.cipher = toJavaCipherSuite(cipher, protocol);
2637 this.protocol = protocol;
2638
2639 if (clientMode) {
2640 if (isEmpty(peerCertificateChain)) {
2641 peerCerts = EmptyArrays.EMPTY_CERTIFICATES;
2642 if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) {
2643 x509PeerCerts = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
2644 } else {
2645 x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED;
2646 }
2647 } else {
2648 peerCerts = new Certificate[peerCertificateChain.length];
2649 if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) {
2650 x509PeerCerts = new X509Certificate[peerCertificateChain.length];
2651 } else {
2652 x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED;
2653 }
2654 initCerts(peerCertificateChain, 0);
2655 }
2656 } else {
2657
2658
2659
2660
2661
2662 if (isEmpty(peerCertificate)) {
2663 peerCerts = EmptyArrays.EMPTY_CERTIFICATES;
2664 x509PeerCerts = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
2665 } else {
2666 if (isEmpty(peerCertificateChain)) {
2667 peerCerts = new Certificate[] {new LazyX509Certificate(peerCertificate)};
2668 if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) {
2669 x509PeerCerts = new X509Certificate[] {
2670 new LazyJavaxX509Certificate(peerCertificate)
2671 };
2672 } else {
2673 x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED;
2674 }
2675 } else {
2676 peerCerts = new Certificate[peerCertificateChain.length + 1];
2677 peerCerts[0] = new LazyX509Certificate(peerCertificate);
2678
2679 if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) {
2680 x509PeerCerts = new X509Certificate[peerCertificateChain.length + 1];
2681 x509PeerCerts[0] = new LazyJavaxX509Certificate(peerCertificate);
2682 } else {
2683 x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED;
2684 }
2685
2686 initCerts(peerCertificateChain, 1);
2687 }
2688 }
2689 }
2690
2691 calculateMaxWrapOverhead();
2692
2693 handshakeState = HandshakeState.FINISHED;
2694 } else {
2695 throw new SSLException("Already closed");
2696 }
2697 }
2698 }
2699
2700 private void initCerts(byte[][] chain, int startPos) {
2701 for (int i = 0; i < chain.length; i++) {
2702 int certPos = startPos + i;
2703 peerCerts[certPos] = new LazyX509Certificate(chain[i]);
2704 if (x509PeerCerts != JAVAX_CERTS_NOT_SUPPORTED) {
2705 x509PeerCerts[certPos] = new LazyJavaxX509Certificate(chain[i]);
2706 }
2707 }
2708 }
2709
2710 @Override
2711 public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
2712 synchronized (ReferenceCountedOpenSslEngine.this) {
2713 if (isEmpty(peerCerts)) {
2714 throw new SSLPeerUnverifiedException("peer not verified");
2715 }
2716 return peerCerts.clone();
2717 }
2718 }
2719
2720 @Override
2721 public boolean hasPeerCertificates() {
2722 synchronized (ReferenceCountedOpenSslEngine.this) {
2723 return !isEmpty(peerCerts);
2724 }
2725 }
2726
2727 @Override
2728 public Certificate[] getLocalCertificates() {
2729 Certificate[] localCerts = localCertificateChain;
2730 if (localCerts == null) {
2731 return null;
2732 }
2733 return localCerts.clone();
2734 }
2735
2736 @Override
2737 public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException {
2738 synchronized (ReferenceCountedOpenSslEngine.this) {
2739 if (x509PeerCerts == JAVAX_CERTS_NOT_SUPPORTED) {
2740
2741
2742 throw new UnsupportedOperationException();
2743 }
2744 if (isEmpty(x509PeerCerts)) {
2745 throw new SSLPeerUnverifiedException("peer not verified");
2746 }
2747 return x509PeerCerts.clone();
2748 }
2749 }
2750
2751 @Override
2752 public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
2753 Certificate[] peer = getPeerCertificates();
2754
2755
2756 return ((java.security.cert.X509Certificate) peer[0]).getSubjectX500Principal();
2757 }
2758
2759 @Override
2760 public Principal getLocalPrincipal() {
2761 Certificate[] local = localCertificateChain;
2762 if (local == null || local.length == 0) {
2763 return null;
2764 }
2765 return ((java.security.cert.X509Certificate) local[0]).getSubjectX500Principal();
2766 }
2767
2768 @Override
2769 public String getCipherSuite() {
2770 synchronized (ReferenceCountedOpenSslEngine.this) {
2771 if (cipher == null) {
2772 return SslUtils.INVALID_CIPHER;
2773 }
2774 return cipher;
2775 }
2776 }
2777
2778 @Override
2779 public String getProtocol() {
2780 String protocol = this.protocol;
2781 if (protocol == null) {
2782 synchronized (ReferenceCountedOpenSslEngine.this) {
2783 if (!destroyed) {
2784 protocol = SSL.getVersion(ssl);
2785 } else {
2786 protocol = StringUtil.EMPTY_STRING;
2787 }
2788 }
2789 }
2790 return protocol;
2791 }
2792
2793 @Override
2794 public String getPeerHost() {
2795 return ReferenceCountedOpenSslEngine.this.getPeerHost();
2796 }
2797
2798 @Override
2799 public int getPeerPort() {
2800 return ReferenceCountedOpenSslEngine.this.getPeerPort();
2801 }
2802
2803 @Override
2804 public int getPacketBufferSize() {
2805 return SSL.SSL_MAX_ENCRYPTED_LENGTH;
2806 }
2807
2808 @Override
2809 public int getApplicationBufferSize() {
2810 return applicationBufferSize;
2811 }
2812
2813 @Override
2814 public void tryExpandApplicationBufferSize(int packetLengthDataOnly) {
2815 if (packetLengthDataOnly > MAX_PLAINTEXT_LENGTH && applicationBufferSize != MAX_RECORD_SIZE) {
2816 applicationBufferSize = MAX_RECORD_SIZE;
2817 }
2818 }
2819
2820 @Override
2821 public String toString() {
2822 return "DefaultOpenSslSession{" +
2823 "sessionContext=" + sessionContext +
2824 ", id=" + id +
2825 '}';
2826 }
2827
2828 @Override
2829 public int hashCode() {
2830 return sessionId().hashCode();
2831 }
2832
2833 @Override
2834 public boolean equals(Object o) {
2835 if (o == this) {
2836 return true;
2837 }
2838
2839 if (!(o instanceof OpenSslInternalSession)) {
2840 return false;
2841 }
2842 return sessionId().equals(((OpenSslInternalSession) o).sessionId());
2843 }
2844 }
2845
2846 private interface NativeSslException {
2847 int errorCode();
2848 }
2849
2850 private static final class OpenSslException extends SSLException implements NativeSslException {
2851 private final int errorCode;
2852
2853 OpenSslException(String reason, int errorCode) {
2854 super(reason);
2855 this.errorCode = errorCode;
2856 }
2857
2858 @Override
2859 public int errorCode() {
2860 return errorCode;
2861 }
2862 }
2863
2864 private static final class OpenSslHandshakeException extends SSLHandshakeException implements NativeSslException {
2865 private final int errorCode;
2866
2867 OpenSslHandshakeException(String reason, int errorCode) {
2868 super(reason);
2869 this.errorCode = errorCode;
2870 }
2871
2872 @Override
2873 public int errorCode() {
2874 return errorCode;
2875 }
2876 }
2877 }