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
424 leak = leakDetection ? leakDetector.track(this) : null;
425 }
426
427 private static boolean isValidHostNameForSNI(String hostname) {
428 try {
429 new SNIHostName(hostname);
430 return true;
431 } catch (IllegalArgumentException illegal) {
432 return false;
433 }
434 }
435
436 final synchronized String[] authMethods() {
437 if (destroyed) {
438 return EMPTY_STRINGS;
439 }
440 return SSL.authenticationMethods(ssl);
441 }
442
443 final void setKeyMaterial(OpenSslKeyMaterial keyMaterial) throws Exception {
444 synchronized (this) {
445 if (destroyed) {
446 return;
447 }
448 SSL.setKeyMaterial(ssl, keyMaterial.certificateChainAddress(), keyMaterial.privateKeyAddress());
449 }
450 session.setLocalCertificate(keyMaterial.certificateChain());
451 }
452
453 final synchronized SecretKeySpec masterKey() {
454 if (destroyed) {
455 return null;
456 }
457 return new SecretKeySpec(SSL.getMasterKey(ssl), "AES");
458 }
459
460 synchronized boolean isSessionReused() {
461 if (destroyed) {
462 return false;
463 }
464 return SSL.isSessionReused(ssl);
465 }
466
467
468
469
470 @UnstableApi
471 public void setOcspResponse(byte[] response) {
472 if (!enableOcsp) {
473 throw new IllegalStateException("OCSP stapling is not enabled");
474 }
475
476 if (clientMode) {
477 throw new IllegalStateException("Not a server SSLEngine");
478 }
479
480 synchronized (this) {
481 if (!destroyed) {
482 SSL.setOcspResponse(ssl, response);
483 }
484 }
485 }
486
487
488
489
490 @UnstableApi
491 public byte[] getOcspResponse() {
492 if (!enableOcsp) {
493 throw new IllegalStateException("OCSP stapling is not enabled");
494 }
495
496 if (!clientMode) {
497 throw new IllegalStateException("Not a client SSLEngine");
498 }
499
500 synchronized (this) {
501 if (destroyed) {
502 return EmptyArrays.EMPTY_BYTES;
503 }
504 return SSL.getOcspResponse(ssl);
505 }
506 }
507
508 @Override
509 public final int refCnt() {
510 return refCnt.refCnt();
511 }
512
513 @Override
514 public final ReferenceCounted retain() {
515 refCnt.retain();
516 return this;
517 }
518
519 @Override
520 public final ReferenceCounted retain(int increment) {
521 refCnt.retain(increment);
522 return this;
523 }
524
525 @Override
526 public final ReferenceCounted touch() {
527 refCnt.touch();
528 return this;
529 }
530
531 @Override
532 public final ReferenceCounted touch(Object hint) {
533 refCnt.touch(hint);
534 return this;
535 }
536
537 @Override
538 public final boolean release() {
539 return refCnt.release();
540 }
541
542 @Override
543 public final boolean release(int decrement) {
544 return refCnt.release(decrement);
545 }
546
547
548
549 public String getApplicationProtocol() {
550 return applicationProtocol;
551 }
552
553
554
555 public String getHandshakeApplicationProtocol() {
556 return applicationProtocol;
557 }
558
559 @Override
560 public final synchronized SSLSession getHandshakeSession() {
561
562
563
564
565 switch(handshakeState) {
566 case NOT_STARTED:
567 case FINISHED:
568 return null;
569 default:
570 return session;
571 }
572 }
573
574
575
576
577
578
579 public final synchronized long sslPointer() {
580 return ssl;
581 }
582
583
584
585
586 public final synchronized void shutdown() {
587 if (!destroyed) {
588 destroyed = true;
589
590
591
592 if (engines != null) {
593 engines.remove(ssl);
594 }
595 SSL.freeSSL(ssl);
596 ssl = networkBIO = 0;
597
598 isInboundDone = outboundClosed = true;
599 }
600
601
602 SSL.clearError();
603 }
604
605
606
607
608
609
610 private int writePlaintextData(final ByteBuffer src, int len) {
611 final int pos = src.position();
612 final int limit = src.limit();
613 final int sslWrote;
614
615 if (src.isDirect()) {
616 sslWrote = SSL.writeToSSL(ssl, bufferAddress(src) + pos, len);
617 if (sslWrote > 0) {
618 src.position(pos + sslWrote);
619 }
620 } else {
621 ByteBuf buf = alloc.directBuffer(len);
622 try {
623 src.limit(pos + len);
624
625 buf.setBytes(0, src);
626 src.limit(limit);
627
628 sslWrote = SSL.writeToSSL(ssl, memoryAddress(buf), len);
629 if (sslWrote > 0) {
630 src.position(pos + sslWrote);
631 } else {
632 src.position(pos);
633 }
634 } finally {
635 buf.release();
636 }
637 }
638 return sslWrote;
639 }
640
641 synchronized void bioSetFd(int fd) {
642 if (!destroyed) {
643 SSL.bioSetFd(this.ssl, fd);
644 }
645 }
646
647
648
649
650 private ByteBuf writeEncryptedData(final ByteBuffer src, int len) throws SSLException {
651 final int pos = src.position();
652 if (src.isDirect()) {
653 SSL.bioSetByteBuffer(networkBIO, bufferAddress(src) + pos, len, false);
654 } else {
655 final ByteBuf buf = alloc.directBuffer(len);
656 try {
657 final int limit = src.limit();
658 src.limit(pos + len);
659 buf.writeBytes(src);
660
661 src.position(pos);
662 src.limit(limit);
663
664 SSL.bioSetByteBuffer(networkBIO, memoryAddress(buf), len, false);
665 return buf;
666 } catch (Throwable cause) {
667 buf.release();
668 PlatformDependent.throwException(cause);
669 }
670 }
671 return null;
672 }
673
674
675
676
677 private int readPlaintextData(final ByteBuffer dst) throws SSLException {
678 final int sslRead;
679 final int pos = dst.position();
680 if (dst.isDirect()) {
681 sslRead = SSL.readFromSSL(ssl, bufferAddress(dst) + pos, dst.limit() - pos);
682 if (sslRead > 0) {
683 dst.position(pos + sslRead);
684 }
685 } else {
686 final int limit = dst.limit();
687 final int len = min(maxEncryptedPacketLength0(), limit - pos);
688 final ByteBuf buf = alloc.directBuffer(len);
689 try {
690 sslRead = SSL.readFromSSL(ssl, memoryAddress(buf), len);
691 if (sslRead > 0) {
692 dst.limit(pos + sslRead);
693 buf.getBytes(buf.readerIndex(), dst);
694 dst.limit(limit);
695 }
696 } finally {
697 buf.release();
698 }
699 }
700
701 return sslRead;
702 }
703
704
705
706
707 final synchronized int maxWrapOverhead() {
708 return maxWrapOverhead;
709 }
710
711
712
713
714 final synchronized int maxEncryptedPacketLength() {
715 return maxEncryptedPacketLength0();
716 }
717
718
719
720
721
722 final int maxEncryptedPacketLength0() {
723 return maxWrapOverhead + MAX_PLAINTEXT_LENGTH;
724 }
725
726
727
728
729
730
731
732
733
734 final int calculateMaxLengthForWrap(int plaintextLength, int numComponents) {
735 return (int) min(maxWrapBufferSize, plaintextLength + (long) maxWrapOverhead * numComponents);
736 }
737
738
739
740
741
742
743
744
745 final int calculateOutNetBufSize(int plaintextLength, int numComponents) {
746 return (int) min(MAX_VALUE, plaintextLength + (long) maxWrapOverhead * numComponents);
747 }
748
749 final synchronized int sslPending() {
750 return sslPending0();
751 }
752
753
754
755
756 private void calculateMaxWrapOverhead() {
757 maxWrapOverhead = SSL.getMaxWrapOverhead(ssl);
758
759
760
761
762 maxWrapBufferSize = jdkCompatibilityMode ? maxEncryptedPacketLength0() : maxEncryptedPacketLength0() << 4;
763 }
764
765 private int sslPending0() {
766
767
768
769
770 return handshakeState != HandshakeState.FINISHED ? 0 : SSL.sslPending(ssl);
771 }
772
773 private boolean isBytesAvailableEnoughForWrap(int bytesAvailable, int plaintextLength, int numComponents) {
774 return bytesAvailable - (long) maxWrapOverhead * numComponents >= plaintextLength;
775 }
776
777 @Override
778 public final SSLEngineResult wrap(
779 final ByteBuffer[] srcs, int offset, final int length, final ByteBuffer dst) throws SSLException {
780
781 checkNotNullWithIAE(srcs, "srcs");
782 checkNotNullWithIAE(dst, "dst");
783
784 if (offset >= srcs.length || offset + length > srcs.length) {
785 throw new IndexOutOfBoundsException(
786 "offset: " + offset + ", length: " + length +
787 " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
788 }
789
790 if (dst.isReadOnly()) {
791 throw new ReadOnlyBufferException();
792 }
793
794 synchronized (this) {
795 if (isOutboundDone()) {
796
797 return isInboundDone() || destroyed ? CLOSED_NOT_HANDSHAKING : NEED_UNWRAP_CLOSED;
798 }
799
800 int bytesProduced = 0;
801 ByteBuf bioReadCopyBuf = null;
802 try {
803
804 if (dst.isDirect()) {
805 SSL.bioSetByteBuffer(networkBIO, bufferAddress(dst) + dst.position(), dst.remaining(),
806 true);
807 } else {
808 bioReadCopyBuf = alloc.directBuffer(dst.remaining());
809 SSL.bioSetByteBuffer(networkBIO, memoryAddress(bioReadCopyBuf), bioReadCopyBuf.writableBytes(),
810 true);
811 }
812
813 int bioLengthBefore = SSL.bioLengthByteBuffer(networkBIO);
814
815
816 if (outboundClosed) {
817
818
819
820
821
822 if (!isBytesAvailableEnoughForWrap(dst.remaining(), 2, 1)) {
823 return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
824 }
825
826
827
828 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
829 if (bytesProduced <= 0) {
830 return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, 0);
831 }
832
833
834
835 if (!doSSLShutdown()) {
836 return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, bytesProduced);
837 }
838 bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
839 return newResultMayFinishHandshake(NEED_WRAP, 0, bytesProduced);
840 }
841
842
843 SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
844 HandshakeState oldHandshakeState = handshakeState;
845
846
847 if (handshakeState != HandshakeState.FINISHED) {
848 if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
849
850 handshakeState = HandshakeState.STARTED_IMPLICITLY;
851 }
852
853
854 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
855
856 if (pendingException != null) {
857
858
859
860
861
862
863
864
865
866
867
868 if (bytesProduced > 0) {
869 return newResult(NEED_WRAP, 0, bytesProduced);
870 }
871
872
873
874 return newResult(handshakeException(), 0, 0);
875 }
876
877 status = handshake();
878
879
880
881 bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
882
883 if (status == NEED_TASK) {
884 return newResult(status, 0, bytesProduced);
885 }
886
887 if (bytesProduced > 0) {
888
889
890
891 return newResult(mayFinishHandshake(status != FINISHED ?
892 bytesProduced == bioLengthBefore ? NEED_WRAP :
893 getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED),
894 0, bytesProduced);
895 }
896
897 if (status == NEED_UNWRAP) {
898
899 return isOutboundDone() ? NEED_UNWRAP_CLOSED : NEED_UNWRAP_OK;
900 }
901
902
903
904 if (outboundClosed) {
905 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
906 return newResultMayFinishHandshake(status, 0, bytesProduced);
907 }
908 }
909
910 final int endOffset = offset + length;
911 if (jdkCompatibilityMode ||
912
913
914
915 oldHandshakeState != HandshakeState.FINISHED) {
916 int srcsLen = 0;
917 for (int i = offset; i < endOffset; ++i) {
918 final ByteBuffer src = srcs[i];
919 if (src == null) {
920 throw new IllegalArgumentException("srcs[" + i + "] is null");
921 }
922 if (srcsLen == MAX_PLAINTEXT_LENGTH) {
923 continue;
924 }
925
926 srcsLen += src.remaining();
927 if (srcsLen > MAX_PLAINTEXT_LENGTH || srcsLen < 0) {
928
929
930
931 srcsLen = MAX_PLAINTEXT_LENGTH;
932 }
933 }
934
935
936
937 if (!isBytesAvailableEnoughForWrap(dst.remaining(), srcsLen, 1)) {
938 return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
939 }
940 }
941
942
943 int bytesConsumed = 0;
944 assert bytesProduced == 0;
945
946
947 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
948
949 if (bytesProduced > 0) {
950 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
951 }
952
953
954 if (pendingException != null) {
955 Throwable error = pendingException;
956 pendingException = null;
957 shutdown();
958
959
960 throw new SSLException(error);
961 }
962
963 for (; offset < endOffset; ++offset) {
964 final ByteBuffer src = srcs[offset];
965 final int remaining = src.remaining();
966 if (remaining == 0) {
967 continue;
968 }
969
970 final int bytesWritten;
971 if (jdkCompatibilityMode) {
972
973
974
975 bytesWritten = writePlaintextData(src, min(remaining, MAX_PLAINTEXT_LENGTH - bytesConsumed));
976 } else {
977
978
979
980 final int availableCapacityForWrap = dst.remaining() - bytesProduced - maxWrapOverhead;
981 if (availableCapacityForWrap <= 0) {
982 return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), bytesConsumed,
983 bytesProduced);
984 }
985 bytesWritten = writePlaintextData(src, min(remaining, availableCapacityForWrap));
986 }
987
988
989
990
991
992
993 final int pendingNow = SSL.bioLengthByteBuffer(networkBIO);
994 bytesProduced += bioLengthBefore - pendingNow;
995 bioLengthBefore = pendingNow;
996
997 if (bytesWritten > 0) {
998 bytesConsumed += bytesWritten;
999
1000 if (jdkCompatibilityMode || bytesProduced == dst.remaining()) {
1001 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
1002 }
1003 } else {
1004 int sslError = SSL.getError(ssl, bytesWritten);
1005 if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
1006
1007 if (!receivedShutdown) {
1008 closeAll();
1009
1010 bytesProduced += bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
1011
1012
1013
1014
1015 SSLEngineResult.HandshakeStatus hs = mayFinishHandshake(
1016 status != FINISHED ? bytesProduced == dst.remaining() ? NEED_WRAP
1017 : getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO))
1018 : FINISHED);
1019 return newResult(hs, bytesConsumed, bytesProduced);
1020 }
1021
1022 return newResult(NOT_HANDSHAKING, bytesConsumed, bytesProduced);
1023 } else if (sslError == SSL.SSL_ERROR_WANT_READ) {
1024
1025
1026
1027 return newResult(NEED_UNWRAP, bytesConsumed, bytesProduced);
1028 } else if (sslError == SSL.SSL_ERROR_WANT_WRITE) {
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041 if (bytesProduced > 0) {
1042
1043
1044 return newResult(NEED_WRAP, bytesConsumed, bytesProduced);
1045 }
1046 return newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced);
1047 } else if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP ||
1048 sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY ||
1049 sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
1050
1051 return newResult(NEED_TASK, bytesConsumed, bytesProduced);
1052 } else {
1053
1054 throw shutdownWithError("SSL_write", sslError, SSL.getLastErrorNumber());
1055 }
1056 }
1057 }
1058 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
1059 } finally {
1060 SSL.bioClearByteBuffer(networkBIO);
1061 if (bioReadCopyBuf == null) {
1062 dst.position(dst.position() + bytesProduced);
1063 } else {
1064 assert bioReadCopyBuf.readableBytes() <= dst.remaining() : "The destination buffer " + dst +
1065 " didn't have enough remaining space to hold the encrypted content in " + bioReadCopyBuf;
1066 dst.put(bioReadCopyBuf.internalNioBuffer(bioReadCopyBuf.readerIndex(), bytesProduced));
1067 bioReadCopyBuf.release();
1068 }
1069 }
1070 }
1071 }
1072
1073 private SSLEngineResult newResult(SSLEngineResult.HandshakeStatus hs, int bytesConsumed, int bytesProduced) {
1074 return newResult(OK, hs, bytesConsumed, bytesProduced);
1075 }
1076
1077 private SSLEngineResult newResult(SSLEngineResult.Status status, SSLEngineResult.HandshakeStatus hs,
1078 int bytesConsumed, int bytesProduced) {
1079
1080
1081
1082 if (isOutboundDone()) {
1083 if (isInboundDone()) {
1084
1085 hs = NOT_HANDSHAKING;
1086
1087
1088 shutdown();
1089 }
1090 return new SSLEngineResult(CLOSED, hs, bytesConsumed, bytesProduced);
1091 }
1092 if (hs == NEED_TASK) {
1093
1094 needTask = true;
1095 }
1096 return new SSLEngineResult(status, hs, bytesConsumed, bytesProduced);
1097 }
1098
1099 private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.HandshakeStatus hs,
1100 int bytesConsumed, int bytesProduced) throws SSLException {
1101 return newResult(mayFinishHandshake(hs, bytesConsumed, bytesProduced), bytesConsumed, bytesProduced);
1102 }
1103
1104 private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.Status status,
1105 SSLEngineResult.HandshakeStatus hs,
1106 int bytesConsumed, int bytesProduced) throws SSLException {
1107 return newResult(status, mayFinishHandshake(hs, bytesConsumed, bytesProduced), bytesConsumed, bytesProduced);
1108 }
1109
1110
1111
1112
1113 private SSLException shutdownWithError(String operation, int sslError, int error) {
1114 if (logger.isDebugEnabled()) {
1115 String errorString = SSL.getErrorString(error);
1116 logger.debug("{} failed with {}: OpenSSL error: {} {}",
1117 operation, sslError, error, errorString);
1118 }
1119
1120
1121 shutdown();
1122
1123 SSLException exception = newSSLExceptionForError(error);
1124
1125 if (pendingException != null) {
1126 exception.initCause(pendingException);
1127 pendingException = null;
1128 }
1129 return exception;
1130 }
1131
1132 private SSLEngineResult handleUnwrapException(int bytesConsumed, int bytesProduced, SSLException e)
1133 throws SSLException {
1134 int lastError = SSL.getLastErrorNumber();
1135 if (lastError != 0) {
1136 return sslReadErrorResult(SSL.SSL_ERROR_SSL, lastError, bytesConsumed,
1137 bytesProduced);
1138 }
1139 throw e;
1140 }
1141
1142 public final SSLEngineResult unwrap(
1143 final ByteBuffer[] srcs, int srcsOffset, final int srcsLength,
1144 final ByteBuffer[] dsts, int dstsOffset, final int dstsLength) throws SSLException {
1145
1146
1147 checkNotNullWithIAE(srcs, "srcs");
1148 if (srcsOffset >= srcs.length
1149 || srcsOffset + srcsLength > srcs.length) {
1150 throw new IndexOutOfBoundsException(
1151 "offset: " + srcsOffset + ", length: " + srcsLength +
1152 " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
1153 }
1154 checkNotNullWithIAE(dsts, "dsts");
1155 if (dstsOffset >= dsts.length || dstsOffset + dstsLength > dsts.length) {
1156 throw new IndexOutOfBoundsException(
1157 "offset: " + dstsOffset + ", length: " + dstsLength +
1158 " (expected: offset <= offset + length <= dsts.length (" + dsts.length + "))");
1159 }
1160 long capacity = 0;
1161 final int dstsEndOffset = dstsOffset + dstsLength;
1162 for (int i = dstsOffset; i < dstsEndOffset; i ++) {
1163 ByteBuffer dst = checkNotNullArrayParam(dsts[i], i, "dsts");
1164 if (dst.isReadOnly()) {
1165 throw new ReadOnlyBufferException();
1166 }
1167 capacity += dst.remaining();
1168 }
1169
1170 final int srcsEndOffset = srcsOffset + srcsLength;
1171 long len = 0;
1172 for (int i = srcsOffset; i < srcsEndOffset; i++) {
1173 ByteBuffer src = checkNotNullArrayParam(srcs[i], i, "srcs");
1174 len += src.remaining();
1175 }
1176
1177 synchronized (this) {
1178 if (isInboundDone()) {
1179 return isOutboundDone() || destroyed ? CLOSED_NOT_HANDSHAKING : NEED_WRAP_CLOSED;
1180 }
1181
1182 SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
1183 HandshakeState oldHandshakeState = handshakeState;
1184
1185 if (handshakeState != HandshakeState.FINISHED) {
1186 if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
1187
1188 handshakeState = HandshakeState.STARTED_IMPLICITLY;
1189 }
1190
1191 status = handshake();
1192
1193 if (status == NEED_TASK) {
1194 return newResult(status, 0, 0);
1195 }
1196
1197 if (status == NEED_WRAP) {
1198 return NEED_WRAP_OK;
1199 }
1200
1201 if (isInboundDone) {
1202 return NEED_WRAP_CLOSED;
1203 }
1204 }
1205
1206 int sslPending = sslPending0();
1207 int packetLength;
1208
1209
1210
1211
1212 if (jdkCompatibilityMode ||
1213
1214
1215
1216 oldHandshakeState != HandshakeState.FINISHED) {
1217 if (len < SSL_RECORD_HEADER_LENGTH) {
1218 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
1219 }
1220
1221 packetLength = SslUtils.getEncryptedPacketLength(srcs, srcsOffset);
1222 if (packetLength == SslUtils.NOT_ENCRYPTED) {
1223 throw new NotSslRecordException("not an SSL/TLS record");
1224 }
1225
1226 assert packetLength >= 0;
1227
1228 final int packetLengthDataOnly = packetLength - SSL_RECORD_HEADER_LENGTH;
1229 if (packetLengthDataOnly > capacity) {
1230
1231
1232 if (packetLengthDataOnly > MAX_RECORD_SIZE) {
1233
1234
1235
1236
1237
1238 throw new SSLException("Illegal packet length: " + packetLengthDataOnly + " > " +
1239 session.getApplicationBufferSize());
1240 } else {
1241 session.tryExpandApplicationBufferSize(packetLengthDataOnly);
1242 }
1243 return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
1244 }
1245
1246 if (len < packetLength) {
1247
1248
1249 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
1250 }
1251 } else if (len == 0 && sslPending <= 0) {
1252 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
1253 } else if (capacity == 0) {
1254 return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
1255 } else {
1256 packetLength = (int) min(MAX_VALUE, len);
1257 }
1258
1259
1260 assert srcsOffset < srcsEndOffset;
1261
1262
1263 assert capacity > 0;
1264
1265
1266 int bytesProduced = 0;
1267 int bytesConsumed = 0;
1268 try {
1269 srcLoop:
1270 for (;;) {
1271 ByteBuffer src = srcs[srcsOffset];
1272 int remaining = src.remaining();
1273 final ByteBuf bioWriteCopyBuf;
1274 int pendingEncryptedBytes;
1275 if (remaining == 0) {
1276 if (sslPending <= 0) {
1277
1278
1279 if (++srcsOffset >= srcsEndOffset) {
1280 break;
1281 }
1282 continue;
1283 } else {
1284 bioWriteCopyBuf = null;
1285 pendingEncryptedBytes = SSL.bioLengthByteBuffer(networkBIO);
1286 }
1287 } else {
1288
1289
1290 pendingEncryptedBytes = min(packetLength, remaining);
1291 try {
1292 bioWriteCopyBuf = writeEncryptedData(src, pendingEncryptedBytes);
1293 } catch (SSLException e) {
1294
1295 return handleUnwrapException(bytesConsumed, bytesProduced, e);
1296 }
1297 }
1298 try {
1299 for (;;) {
1300 ByteBuffer dst = dsts[dstsOffset];
1301 if (!dst.hasRemaining()) {
1302
1303 if (++dstsOffset >= dstsEndOffset) {
1304 break srcLoop;
1305 }
1306 continue;
1307 }
1308
1309 int bytesRead;
1310 try {
1311 bytesRead = readPlaintextData(dst);
1312 } catch (SSLException e) {
1313
1314 return handleUnwrapException(bytesConsumed, bytesProduced, e);
1315 }
1316
1317
1318
1319 int localBytesConsumed = pendingEncryptedBytes - SSL.bioLengthByteBuffer(networkBIO);
1320 bytesConsumed += localBytesConsumed;
1321 packetLength -= localBytesConsumed;
1322 pendingEncryptedBytes -= localBytesConsumed;
1323 src.position(src.position() + localBytesConsumed);
1324
1325 if (bytesRead > 0) {
1326 bytesProduced += bytesRead;
1327
1328 if (!dst.hasRemaining()) {
1329 sslPending = sslPending0();
1330
1331 if (++dstsOffset >= dstsEndOffset) {
1332 return sslPending > 0 ?
1333 newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced) :
1334 newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1335 bytesConsumed, bytesProduced);
1336 }
1337 } else if (packetLength == 0 || jdkCompatibilityMode) {
1338
1339
1340 break srcLoop;
1341 }
1342 } else {
1343 int sslError = SSL.getError(ssl, bytesRead);
1344 if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
1345
1346
1347 break;
1348 } else if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
1349
1350 if (!receivedShutdown) {
1351 closeAll();
1352 }
1353 return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1354 bytesConsumed, bytesProduced);
1355 } else if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP ||
1356 sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY ||
1357 sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
1358 return newResult(isInboundDone() ? CLOSED : OK,
1359 NEED_TASK, bytesConsumed, bytesProduced);
1360 } else {
1361 return sslReadErrorResult(sslError, SSL.getLastErrorNumber(), bytesConsumed,
1362 bytesProduced);
1363 }
1364 }
1365 }
1366
1367 if (++srcsOffset >= srcsEndOffset) {
1368 break;
1369 }
1370 } finally {
1371 if (bioWriteCopyBuf != null) {
1372 bioWriteCopyBuf.release();
1373 }
1374 }
1375 }
1376 } finally {
1377 SSL.bioClearByteBuffer(networkBIO);
1378 rejectRemoteInitiatedRenegotiation();
1379 }
1380
1381
1382 if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) {
1383 closeAll();
1384 }
1385
1386 return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, bytesConsumed, bytesProduced);
1387 }
1388 }
1389
1390 private boolean needWrapAgain(int stackError) {
1391
1392
1393
1394
1395 if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1396
1397
1398 if (pendingException == null) {
1399 pendingException = newSSLExceptionForError(stackError);
1400 } else if (shouldAddSuppressed(pendingException, stackError)) {
1401 ThrowableUtil.addSuppressed(pendingException, newSSLExceptionForError(stackError));
1402 }
1403
1404
1405 SSL.clearError();
1406 return true;
1407 }
1408 return false;
1409 }
1410
1411 private SSLException newSSLExceptionForError(int stackError) {
1412 String message = SSL.getErrorString(stackError);
1413 return handshakeState == HandshakeState.FINISHED ?
1414 new OpenSslException(message, stackError) : new OpenSslHandshakeException(message, stackError);
1415 }
1416
1417 private static boolean shouldAddSuppressed(Throwable target, int errorCode) {
1418 for (Throwable suppressed: ThrowableUtil.getSuppressed(target)) {
1419 if (suppressed instanceof NativeSslException &&
1420 ((NativeSslException) suppressed).errorCode() == errorCode) {
1421
1422 return false;
1423 }
1424 }
1425 return true;
1426 }
1427
1428 private SSLEngineResult sslReadErrorResult(int error, int stackError, int bytesConsumed, int bytesProduced)
1429 throws SSLException {
1430 if (needWrapAgain(stackError)) {
1431
1432
1433 return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced);
1434 }
1435 throw shutdownWithError("SSL_read", error, stackError);
1436 }
1437
1438 private void closeAll() throws SSLException {
1439 receivedShutdown = true;
1440 closeOutbound();
1441 closeInbound();
1442 }
1443
1444 private void rejectRemoteInitiatedRenegotiation() throws SSLHandshakeException {
1445
1446
1447 if (destroyed || SslProtocols.TLS_v1_3.equals(session.getProtocol())
1448 || handshakeState != HandshakeState.FINISHED) {
1449 return;
1450 }
1451
1452 int count = SSL.getHandshakeCount(ssl);
1453 boolean renegotiationAttempted = (!clientMode && count > 1) || (clientMode && count > 2);
1454 if (renegotiationAttempted) {
1455 shutdown();
1456 throw new SSLHandshakeException("remote-initiated renegotiation not allowed");
1457 }
1458 }
1459
1460 public final SSLEngineResult unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts) throws SSLException {
1461 return unwrap(srcs, 0, srcs.length, dsts, 0, dsts.length);
1462 }
1463
1464 private ByteBuffer[] singleSrcBuffer(ByteBuffer src) {
1465 singleSrcBuffer[0] = src;
1466 return singleSrcBuffer;
1467 }
1468
1469 private void resetSingleSrcBuffer() {
1470 singleSrcBuffer[0] = null;
1471 }
1472
1473 private ByteBuffer[] singleDstBuffer(ByteBuffer src) {
1474 singleDstBuffer[0] = src;
1475 return singleDstBuffer;
1476 }
1477
1478 private void resetSingleDstBuffer() {
1479 singleDstBuffer[0] = null;
1480 }
1481
1482 @Override
1483 public final synchronized SSLEngineResult unwrap(
1484 final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException {
1485 try {
1486 return unwrap(singleSrcBuffer(src), 0, 1, dsts, offset, length);
1487 } finally {
1488 resetSingleSrcBuffer();
1489 }
1490 }
1491
1492 @Override
1493 public final synchronized SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1494 try {
1495 return wrap(singleSrcBuffer(src), dst);
1496 } finally {
1497 resetSingleSrcBuffer();
1498 }
1499 }
1500
1501 @Override
1502 public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1503 try {
1504 return unwrap(singleSrcBuffer(src), singleDstBuffer(dst));
1505 } finally {
1506 resetSingleSrcBuffer();
1507 resetSingleDstBuffer();
1508 }
1509 }
1510
1511 @Override
1512 public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException {
1513 try {
1514 return unwrap(singleSrcBuffer(src), dsts);
1515 } finally {
1516 resetSingleSrcBuffer();
1517 }
1518 }
1519
1520 private final class AsyncTaskDecorator implements AsyncRunnable, Runnable {
1521
1522 private final AsyncTask task;
1523
1524 AsyncTaskDecorator(AsyncTask task) {
1525 this.task = task;
1526 }
1527
1528 @Override
1529 public void run(final Runnable runnable) {
1530 if (destroyed) {
1531
1532 return;
1533 }
1534 task.runAsync(() -> runAndResetNeedTask(runnable));
1535 }
1536
1537 @Override
1538 public void run() {
1539 runAndResetNeedTask(task);
1540 }
1541 }
1542
1543 private void runAndResetNeedTask(Runnable task) {
1544
1545
1546 synchronized (ReferenceCountedOpenSslEngine.this) {
1547 try {
1548 if (destroyed) {
1549
1550 return;
1551 }
1552 task.run();
1553 if (handshakeState != HandshakeState.FINISHED && !destroyed) {
1554
1555
1556
1557 if (SSL.doHandshake(ssl) <= 0) {
1558 SSL.clearError();
1559 }
1560 }
1561 } finally {
1562
1563 needTask = false;
1564 }
1565 }
1566 }
1567
1568 @Override
1569 public final synchronized Runnable getDelegatedTask() {
1570 if (destroyed) {
1571 return null;
1572 }
1573 final Runnable task = SSL.getTask(ssl);
1574 if (task == null) {
1575 return null;
1576 }
1577 if (task instanceof AsyncTask) {
1578 return new AsyncTaskDecorator((AsyncTask) task);
1579 }
1580 return () -> runAndResetNeedTask(task);
1581 }
1582
1583 @Override
1584 public final synchronized void closeInbound() throws SSLException {
1585 if (isInboundDone) {
1586 return;
1587 }
1588
1589 isInboundDone = true;
1590
1591 if (isOutboundDone()) {
1592
1593
1594 shutdown();
1595 }
1596
1597 if (handshakeState != HandshakeState.NOT_STARTED && !receivedShutdown) {
1598 throw new SSLException(
1599 "Inbound closed before receiving peer's close_notify: possible truncation attack?");
1600 }
1601 }
1602
1603 @Override
1604 public final synchronized boolean isInboundDone() {
1605 return isInboundDone;
1606 }
1607
1608 @Override
1609 public final synchronized void closeOutbound() {
1610 if (outboundClosed) {
1611 return;
1612 }
1613
1614 outboundClosed = true;
1615
1616 if (handshakeState != HandshakeState.NOT_STARTED && !destroyed) {
1617 int mode = SSL.getShutdown(ssl);
1618 if ((mode & SSL.SSL_SENT_SHUTDOWN) != SSL.SSL_SENT_SHUTDOWN) {
1619 doSSLShutdown();
1620 }
1621 } else {
1622
1623 shutdown();
1624 }
1625 }
1626
1627
1628
1629
1630
1631 private boolean doSSLShutdown() {
1632 if (SSL.isInInit(ssl) != 0) {
1633
1634
1635
1636
1637 return false;
1638 }
1639 int err = SSL.shutdownSSL(ssl);
1640 if (err < 0) {
1641 int sslErr = SSL.getError(ssl, err);
1642 if (sslErr == SSL.SSL_ERROR_SYSCALL || sslErr == SSL.SSL_ERROR_SSL) {
1643 if (logger.isDebugEnabled()) {
1644 int error = SSL.getLastErrorNumber();
1645 logger.debug("SSL_shutdown failed: OpenSSL error: {} {}", error, SSL.getErrorString(error));
1646 }
1647
1648 shutdown();
1649 return false;
1650 }
1651 SSL.clearError();
1652 }
1653 return true;
1654 }
1655
1656 @Override
1657 public final synchronized boolean isOutboundDone() {
1658
1659
1660 return outboundClosed && (networkBIO == 0 || SSL.bioLengthNonApplication(networkBIO) == 0);
1661 }
1662
1663 @Override
1664 public final String[] getSupportedCipherSuites() {
1665 return OpenSsl.AVAILABLE_CIPHER_SUITES.toArray(EMPTY_STRINGS);
1666 }
1667
1668 @Override
1669 public final String[] getEnabledCipherSuites() {
1670 final String[] extraCiphers;
1671 final String[] enabled;
1672 final boolean tls13Enabled;
1673 synchronized (this) {
1674 if (!destroyed) {
1675 enabled = SSL.getCiphers(ssl);
1676 int opts = SSL.getOptions(ssl);
1677 if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_3, SslProtocols.TLS_v1_3)) {
1678 extraCiphers = OpenSsl.EXTRA_SUPPORTED_TLS_1_3_CIPHERS;
1679 tls13Enabled = true;
1680 } else {
1681 extraCiphers = EMPTY_STRINGS;
1682 tls13Enabled = false;
1683 }
1684 } else {
1685 return EMPTY_STRINGS;
1686 }
1687 }
1688 if (enabled == null) {
1689 return EMPTY_STRINGS;
1690 } else {
1691 Set<String> enabledSet = new LinkedHashSet<>(enabled.length + extraCiphers.length);
1692 synchronized (this) {
1693 for (String enabledCipher : enabled) {
1694 String mapped = toJavaCipherSuite(enabledCipher);
1695 final String cipher = mapped == null ? enabledCipher : mapped;
1696 if ((!tls13Enabled || !OpenSsl.isTlsv13Supported()) && SslUtils.isTLSv13Cipher(cipher)) {
1697 continue;
1698 }
1699 enabledSet.add(cipher);
1700 }
1701 Collections.addAll(enabledSet, extraCiphers);
1702 }
1703 return enabledSet.toArray(EMPTY_STRINGS);
1704 }
1705 }
1706
1707 @Override
1708 public final void setEnabledCipherSuites(String[] cipherSuites) {
1709 checkNotNull(cipherSuites, "cipherSuites");
1710
1711 final StringBuilder buf = new StringBuilder();
1712 final StringBuilder bufTLSv13 = new StringBuilder();
1713
1714 CipherSuiteConverter.convertToCipherStrings(Arrays.asList(cipherSuites), buf, bufTLSv13,
1715 OpenSsl.isBoringSSL());
1716 final String cipherSuiteSpec = buf.toString();
1717 final String cipherSuiteSpecTLSv13 = bufTLSv13.toString();
1718
1719 if (!OpenSsl.isTlsv13Supported() && !cipherSuiteSpecTLSv13.isEmpty()) {
1720 throw new IllegalArgumentException("TLSv1.3 is not supported by this java version.");
1721 }
1722 synchronized (this) {
1723 hasTLSv13Cipher = !cipherSuiteSpecTLSv13.isEmpty();
1724 if (!destroyed) {
1725 try {
1726
1727 SSL.setCipherSuites(ssl, cipherSuiteSpec, false);
1728 if (OpenSsl.isTlsv13Supported()) {
1729
1730 SSL.setCipherSuites(ssl, OpenSsl.checkTls13Ciphers(logger, cipherSuiteSpecTLSv13), true);
1731 }
1732
1733
1734
1735 Set<String> protocols = new HashSet<String>(enabledProtocols);
1736
1737
1738
1739 if (cipherSuiteSpec.isEmpty()) {
1740 protocols.remove(SslProtocols.TLS_v1);
1741 protocols.remove(SslProtocols.TLS_v1_1);
1742 protocols.remove(SslProtocols.TLS_v1_2);
1743 protocols.remove(SslProtocols.SSL_v3);
1744 protocols.remove(SslProtocols.SSL_v2);
1745 protocols.remove(SslProtocols.SSL_v2_HELLO);
1746 }
1747
1748 if (cipherSuiteSpecTLSv13.isEmpty()) {
1749 protocols.remove(SslProtocols.TLS_v1_3);
1750 }
1751
1752
1753 setEnabledProtocols0(protocols.toArray(EMPTY_STRINGS), !hasTLSv13Cipher);
1754 } catch (Exception e) {
1755 throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec, e);
1756 }
1757 } else {
1758 throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec);
1759 }
1760 }
1761 }
1762
1763 @Override
1764 public final String[] getSupportedProtocols() {
1765 return OpenSsl.unpackSupportedProtocols().toArray(EMPTY_STRINGS);
1766 }
1767
1768 @Override
1769 public final String[] getEnabledProtocols() {
1770 return enabledProtocols.toArray(EMPTY_STRINGS);
1771 }
1772
1773 private static boolean isProtocolEnabled(int opts, int disableMask, String protocolString) {
1774
1775
1776 return (opts & disableMask) == 0 && OpenSsl.isProtocolSupported(protocolString);
1777 }
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788 @Override
1789 public final void setEnabledProtocols(String[] protocols) {
1790 checkNotNullWithIAE(protocols, "protocols");
1791 synchronized (this) {
1792 enabledProtocols.clear();
1793
1794 enabledProtocols.add(SslProtocols.SSL_v2_HELLO);
1795
1796 Collections.addAll(enabledProtocols, protocols);
1797
1798 setEnabledProtocols0(protocols, !hasTLSv13Cipher);
1799 }
1800 }
1801
1802 private void setEnabledProtocols0(String[] protocols, boolean explicitDisableTLSv13) {
1803 assert Thread.holdsLock(this);
1804
1805 int minProtocolIndex = OPENSSL_OP_NO_PROTOCOLS.length;
1806 int maxProtocolIndex = 0;
1807 for (String protocol : protocols) {
1808 if (!OpenSsl.isProtocolSupported(protocol)) {
1809 throw new IllegalArgumentException("Protocol " + protocol + " is not supported.");
1810 }
1811
1812 int index;
1813 switch (protocol) {
1814 case SslProtocols.SSL_v2:
1815 index = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2;
1816 break;
1817 case SslProtocols.SSL_v3:
1818 index = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3;
1819 break;
1820 case SslProtocols.TLS_v1:
1821 index = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1;
1822 break;
1823 case SslProtocols.TLS_v1_1:
1824 index = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1;
1825 break;
1826 case SslProtocols.TLS_v1_2:
1827 index = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
1828 break;
1829 case SslProtocols.TLS_v1_3:
1830 if (explicitDisableTLSv13) {
1831 continue;
1832 }
1833 index = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3;
1834 break;
1835 default:
1836 continue;
1837 }
1838
1839 minProtocolIndex = Math.min(minProtocolIndex, index);
1840 maxProtocolIndex = Math.max(maxProtocolIndex, index);
1841 }
1842
1843 if (destroyed) {
1844 throw new IllegalStateException("failed to enable protocols: " + Arrays.asList(protocols));
1845 }
1846
1847 SSL.clearOptions(ssl, SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 |
1848 SSL.SSL_OP_NO_TLSv1 | SSL.SSL_OP_NO_TLSv1_1 |
1849 SSL.SSL_OP_NO_TLSv1_2 | SSL.SSL_OP_NO_TLSv1_3);
1850
1851 int opts = 0;
1852 for (int i = 0; i < minProtocolIndex; ++i) {
1853 opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1854 }
1855 assert maxProtocolIndex != MAX_VALUE;
1856 for (int i = maxProtocolIndex + 1; i < OPENSSL_OP_NO_PROTOCOLS.length; ++i) {
1857 opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1858 }
1859
1860 SSL.setOptions(ssl, opts);
1861 }
1862
1863 @Override
1864 public final SSLSession getSession() {
1865 return session;
1866 }
1867
1868 @Override
1869 public final synchronized void beginHandshake() throws SSLException {
1870 switch (handshakeState) {
1871 case STARTED_IMPLICITLY:
1872 checkEngineClosed();
1873
1874
1875
1876
1877
1878
1879
1880 handshakeState = HandshakeState.STARTED_EXPLICITLY;
1881 calculateMaxWrapOverhead();
1882
1883 break;
1884 case STARTED_EXPLICITLY:
1885
1886 break;
1887 case FINISHED:
1888 throw new SSLException("renegotiation unsupported");
1889 case NOT_STARTED:
1890 handshakeState = HandshakeState.STARTED_EXPLICITLY;
1891 if (handshake() == NEED_TASK) {
1892
1893 needTask = true;
1894 }
1895 calculateMaxWrapOverhead();
1896 break;
1897 default:
1898 throw new Error("Unexpected handshake state: " + handshakeState);
1899 }
1900 }
1901
1902 private void checkEngineClosed() throws SSLException {
1903 if (destroyed) {
1904 throw new SSLException("engine closed");
1905 }
1906 }
1907
1908 private static SSLEngineResult.HandshakeStatus pendingStatus(int pendingStatus) {
1909
1910 return pendingStatus > 0 ? NEED_WRAP : NEED_UNWRAP;
1911 }
1912
1913 private static boolean isEmpty(Object[] arr) {
1914 return arr == null || arr.length == 0;
1915 }
1916
1917 private static boolean isEmpty(byte[] cert) {
1918 return cert == null || cert.length == 0;
1919 }
1920
1921 private SSLEngineResult.HandshakeStatus handshakeException() throws SSLException {
1922 if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1923
1924 return NEED_WRAP;
1925 }
1926
1927 Throwable exception = pendingException;
1928 assert exception != null;
1929 pendingException = null;
1930 shutdown();
1931 if (exception instanceof SSLHandshakeException) {
1932 throw (SSLHandshakeException) exception;
1933 }
1934 SSLHandshakeException e = new SSLHandshakeException("General OpenSslEngine problem");
1935 e.initCause(exception);
1936 throw e;
1937 }
1938
1939
1940
1941
1942
1943 final void initHandshakeException(Throwable cause) {
1944 if (pendingException == null) {
1945 pendingException = cause;
1946 } else {
1947 ThrowableUtil.addSuppressed(pendingException, cause);
1948 }
1949 }
1950
1951 private SSLEngineResult.HandshakeStatus handshake() throws SSLException {
1952 if (needTask) {
1953 return NEED_TASK;
1954 }
1955 if (handshakeState == HandshakeState.FINISHED) {
1956 return FINISHED;
1957 }
1958
1959 checkEngineClosed();
1960
1961 if (pendingException != null) {
1962
1963
1964 if (SSL.doHandshake(ssl) <= 0) {
1965
1966 SSL.clearError();
1967 }
1968 return handshakeException();
1969 }
1970
1971
1972 engines.put(sslPointer(), this);
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 String prefix = toJavaCipherSuitePrefix(version);
2085 return CipherSuiteConverter.toJava(openSslCipherSuite, prefix);
2086 }
2087
2088
2089
2090
2091 private static String toJavaCipherSuitePrefix(String protocolVersion) {
2092 final char c;
2093 if (protocolVersion == null || protocolVersion.isEmpty()) {
2094 c = 0;
2095 } else {
2096 c = protocolVersion.charAt(0);
2097 }
2098
2099 switch (c) {
2100 case 'T':
2101 return "TLS";
2102 case 'S':
2103 return "SSL";
2104 default:
2105 return "UNKNOWN";
2106 }
2107 }
2108
2109 @Override
2110 public final void setUseClientMode(boolean clientMode) {
2111 if (clientMode != this.clientMode) {
2112 throw new UnsupportedOperationException();
2113 }
2114 }
2115
2116 @Override
2117 public final boolean getUseClientMode() {
2118 return clientMode;
2119 }
2120
2121 @Override
2122 public final void setNeedClientAuth(boolean b) {
2123 setClientAuth(b ? ClientAuth.REQUIRE : ClientAuth.NONE);
2124 }
2125
2126 @Override
2127 public final boolean getNeedClientAuth() {
2128 return clientAuth == ClientAuth.REQUIRE;
2129 }
2130
2131 @Override
2132 public final void setWantClientAuth(boolean b) {
2133 setClientAuth(b ? ClientAuth.OPTIONAL : ClientAuth.NONE);
2134 }
2135
2136 @Override
2137 public final boolean getWantClientAuth() {
2138 return clientAuth == ClientAuth.OPTIONAL;
2139 }
2140
2141
2142
2143
2144
2145 @UnstableApi
2146 public final synchronized void setVerify(int verifyMode, int depth) {
2147 if (!destroyed) {
2148 SSL.setVerify(ssl, verifyMode, depth);
2149 }
2150 }
2151
2152 private void setClientAuth(ClientAuth mode) {
2153 if (clientMode) {
2154 return;
2155 }
2156 synchronized (this) {
2157 if (clientAuth == mode) {
2158
2159 return;
2160 }
2161 if (!destroyed) {
2162 switch (mode) {
2163 case NONE:
2164 SSL.setVerify(ssl, SSL.SSL_CVERIFY_NONE, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
2165 break;
2166 case REQUIRE:
2167 SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
2168 break;
2169 case OPTIONAL:
2170 SSL.setVerify(ssl, SSL.SSL_CVERIFY_OPTIONAL, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
2171 break;
2172 default:
2173 throw new Error("Unexpected client auth mode: " + mode);
2174 }
2175 }
2176 clientAuth = mode;
2177 }
2178 }
2179
2180 @Override
2181 public final void setEnableSessionCreation(boolean b) {
2182 if (b) {
2183 throw new UnsupportedOperationException();
2184 }
2185 }
2186
2187 @Override
2188 public final boolean getEnableSessionCreation() {
2189 return false;
2190 }
2191
2192 @Override
2193 public final synchronized SSLParameters getSSLParameters() {
2194 SSLParameters sslParameters = super.getSSLParameters();
2195
2196 sslParameters.setEndpointIdentificationAlgorithm(endpointIdentificationAlgorithm);
2197 sslParameters.setAlgorithmConstraints(algorithmConstraints);
2198 sslParameters.setServerNames(serverNames);
2199 if (groups != null) {
2200 OpenSslParametersUtil.setNamesGroups(sslParameters, groups.clone());
2201 }
2202 if (!destroyed) {
2203 sslParameters.setUseCipherSuitesOrder((SSL.getOptions(ssl) & SSL.SSL_OP_CIPHER_SERVER_PREFERENCE) != 0);
2204 }
2205
2206 sslParameters.setSNIMatchers(matchers);
2207 return sslParameters;
2208 }
2209
2210 @Override
2211 public final synchronized void setSSLParameters(SSLParameters sslParameters) {
2212 if (sslParameters.getAlgorithmConstraints() != null) {
2213 throw new IllegalArgumentException("AlgorithmConstraints are not supported.");
2214 }
2215
2216 boolean isDestroyed = destroyed;
2217 if (!isDestroyed) {
2218 if (clientMode) {
2219 List<SNIServerName> proposedServerNames = sslParameters.getServerNames();
2220 if (proposedServerNames != null && !proposedServerNames.isEmpty()) {
2221 for (SNIServerName serverName : proposedServerNames) {
2222 if (!(serverName instanceof SNIHostName)) {
2223 throw new IllegalArgumentException("Only " + SNIHostName.class.getName()
2224 + " instances are supported, but found: " + serverName);
2225 }
2226 }
2227 for (SNIServerName serverName : proposedServerNames) {
2228 SNIHostName name = (SNIHostName) serverName;
2229 SSL.setTlsExtHostName(ssl, name.getAsciiName());
2230 }
2231 }
2232 serverNames = proposedServerNames;
2233 }
2234
2235 String[] groups = OpenSslParametersUtil.getNamesGroups(sslParameters);
2236 if (groups != null) {
2237 Set<String> groupsSet = new LinkedHashSet<String>(groups.length);
2238 for (String group : groups) {
2239 if (group == null || group.isEmpty()) {
2240
2241 throw new IllegalArgumentException();
2242 }
2243 if (!groupsSet.add(GroupsConverter.toOpenSsl(group))) {
2244
2245 throw new IllegalArgumentException("named groups contains a duplicate");
2246 }
2247 }
2248 if (!SSL.setCurvesList(ssl, groupsSet.toArray(EMPTY_STRINGS))) {
2249 throw new UnsupportedOperationException();
2250 }
2251 this.groups = groups;
2252 }
2253 if (sslParameters.getUseCipherSuitesOrder()) {
2254 SSL.setOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
2255 } else {
2256 SSL.clearOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
2257 }
2258 }
2259 matchers = sslParameters.getSNIMatchers();
2260
2261 final String endpointIdentificationAlgorithm = sslParameters.getEndpointIdentificationAlgorithm();
2262 if (!isDestroyed) {
2263 configureEndpointVerification(endpointIdentificationAlgorithm);
2264 }
2265 this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
2266 algorithmConstraints = sslParameters.getAlgorithmConstraints();
2267 super.setSSLParameters(sslParameters);
2268 }
2269
2270 private void configureEndpointVerification(String endpointIdentificationAlgorithm) {
2271
2272
2273 if (clientMode && isEndPointVerificationEnabled(endpointIdentificationAlgorithm)) {
2274 SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, -1);
2275 }
2276 }
2277
2278 private static boolean isEndPointVerificationEnabled(String endPointIdentificationAlgorithm) {
2279 return endPointIdentificationAlgorithm != null && !endPointIdentificationAlgorithm.isEmpty();
2280 }
2281
2282 final boolean checkSniHostnameMatch(String hostname) {
2283 Collection<SNIMatcher> matchers = this.matchers;
2284 if (matchers != null && !matchers.isEmpty()) {
2285 SNIHostName name = new SNIHostName(hostname.getBytes(CharsetUtil.UTF_8));
2286 for (SNIMatcher matcher : matchers) {
2287
2288 if (matcher.getType() == 0 && matcher.matches(name)) {
2289 return true;
2290 }
2291 }
2292 return false;
2293 }
2294 return true;
2295 }
2296
2297 @Override
2298 public String getNegotiatedApplicationProtocol() {
2299 return applicationProtocol;
2300 }
2301
2302 private static long bufferAddress(ByteBuffer b) {
2303 assert b.isDirect();
2304 if (PlatformDependent.hasUnsafe()) {
2305 return PlatformDependent.directBufferAddress(b);
2306 }
2307 return Buffer.address(b);
2308 }
2309
2310
2311
2312
2313 private void selectApplicationProtocol() throws SSLException {
2314 ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior = apn.selectedListenerFailureBehavior();
2315 List<String> protocols = apn.protocols();
2316 String applicationProtocol;
2317 switch (apn.protocol()) {
2318 case NONE:
2319 break;
2320
2321
2322 case ALPN:
2323 applicationProtocol = SSL.getAlpnSelected(ssl);
2324 if (applicationProtocol != null) {
2325 this.applicationProtocol = selectApplicationProtocol(
2326 protocols, behavior, applicationProtocol);
2327 }
2328 break;
2329 case NPN:
2330 applicationProtocol = SSL.getNextProtoNegotiated(ssl);
2331 if (applicationProtocol != null) {
2332 this.applicationProtocol = selectApplicationProtocol(
2333 protocols, behavior, applicationProtocol);
2334 }
2335 break;
2336 case NPN_AND_ALPN:
2337 applicationProtocol = SSL.getAlpnSelected(ssl);
2338 if (applicationProtocol == null) {
2339 applicationProtocol = SSL.getNextProtoNegotiated(ssl);
2340 }
2341 if (applicationProtocol != null) {
2342 this.applicationProtocol = selectApplicationProtocol(
2343 protocols, behavior, applicationProtocol);
2344 }
2345 break;
2346 default:
2347 throw new Error("Unexpected apn protocol: " + apn.protocol());
2348 }
2349 }
2350
2351 private static String selectApplicationProtocol(List<String> protocols,
2352 ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior,
2353 String applicationProtocol) throws SSLException {
2354 if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT) {
2355 return applicationProtocol;
2356 } else {
2357 int size = protocols.size();
2358 assert size > 0;
2359 if (protocols.contains(applicationProtocol)) {
2360 return applicationProtocol;
2361 } else {
2362 if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.CHOOSE_MY_LAST_PROTOCOL) {
2363 return protocols.get(size - 1);
2364 } else {
2365 throw new SSLException("unknown protocol " + applicationProtocol);
2366 }
2367 }
2368 }
2369 }
2370
2371 private static final X509Certificate[] JAVAX_CERTS_NOT_SUPPORTED = new X509Certificate[0];
2372
2373 private final class DefaultOpenSslSession implements OpenSslInternalSession {
2374 private final OpenSslSessionContext sessionContext;
2375
2376
2377
2378 private X509Certificate[] x509PeerCerts;
2379 private Certificate[] peerCerts;
2380
2381 private boolean valid = true;
2382 private String protocol;
2383 private String cipher;
2384 private OpenSslSessionId id = OpenSslSessionId.NULL_ID;
2385 private long creationTime;
2386
2387
2388 private long lastAccessed = -1;
2389
2390 private volatile int applicationBufferSize = MAX_PLAINTEXT_LENGTH;
2391 private volatile Certificate[] localCertificateChain;
2392 private volatile Map<String, Object> keyValueStorage = new ConcurrentHashMap<String, Object>();
2393
2394 DefaultOpenSslSession(OpenSslSessionContext sessionContext) {
2395 this.sessionContext = sessionContext;
2396 }
2397
2398 private SSLSessionBindingEvent newSSLSessionBindingEvent(String name) {
2399 return new SSLSessionBindingEvent(session, name);
2400 }
2401
2402 @Override
2403 public void prepareHandshake() {
2404 keyValueStorage.clear();
2405 }
2406
2407 @Override
2408 public void setSessionDetails(
2409 long creationTime, long lastAccessedTime, OpenSslSessionId sessionId,
2410 Map<String, Object> keyValueStorage) {
2411 synchronized (ReferenceCountedOpenSslEngine.this) {
2412 if (id == OpenSslSessionId.NULL_ID) {
2413 id = sessionId;
2414 this.creationTime = creationTime;
2415 lastAccessed = lastAccessedTime;
2416
2417
2418
2419
2420 this.keyValueStorage = keyValueStorage;
2421 }
2422 }
2423 }
2424
2425 @Override
2426 public Map<String, Object> keyValueStorage() {
2427 return keyValueStorage;
2428 }
2429
2430 @Override
2431 public OpenSslSessionId sessionId() {
2432 synchronized (ReferenceCountedOpenSslEngine.this) {
2433 if (this.id == OpenSslSessionId.NULL_ID && !destroyed) {
2434 byte[] sessionId = SSL.getSessionId(ssl);
2435 if (sessionId != null) {
2436 id = new OpenSslSessionId(sessionId);
2437 }
2438 }
2439
2440 return id;
2441 }
2442 }
2443
2444 @Override
2445 public void setLocalCertificate(Certificate[] localCertificate) {
2446 localCertificateChain = localCertificate;
2447 }
2448
2449 @Override
2450 public byte[] getId() {
2451 return sessionId().cloneBytes();
2452 }
2453
2454 @Override
2455 public OpenSslSessionContext getSessionContext() {
2456 return sessionContext;
2457 }
2458
2459 @Override
2460 public long getCreationTime() {
2461 synchronized (ReferenceCountedOpenSslEngine.this) {
2462 return creationTime;
2463 }
2464 }
2465
2466 @Override
2467 public void setLastAccessedTime(long time) {
2468 synchronized (ReferenceCountedOpenSslEngine.this) {
2469 lastAccessed = time;
2470 }
2471 }
2472
2473 @Override
2474 public long getLastAccessedTime() {
2475
2476 synchronized (ReferenceCountedOpenSslEngine.this) {
2477 return lastAccessed == -1 ? creationTime : lastAccessed;
2478 }
2479 }
2480
2481 @Override
2482 public void invalidate() {
2483 synchronized (ReferenceCountedOpenSslEngine.this) {
2484 valid = false;
2485 sessionContext.removeFromCache(id);
2486 }
2487 }
2488
2489 @Override
2490 public boolean isValid() {
2491 synchronized (ReferenceCountedOpenSslEngine.this) {
2492 return valid || sessionContext.isInCache(id);
2493 }
2494 }
2495
2496 @Override
2497 public void putValue(String name, Object value) {
2498 checkNotNull(name, "name");
2499 checkNotNull(value, "value");
2500
2501 final Object old = keyValueStorage.put(name, value);
2502 if (value instanceof SSLSessionBindingListener) {
2503
2504 ((SSLSessionBindingListener) value).valueBound(newSSLSessionBindingEvent(name));
2505 }
2506 notifyUnbound(old, name);
2507 }
2508
2509 @Override
2510 public Object getValue(String name) {
2511 checkNotNull(name, "name");
2512 return keyValueStorage.get(name);
2513 }
2514
2515 @Override
2516 public void removeValue(String name) {
2517 checkNotNull(name, "name");
2518 final Object old = keyValueStorage.remove(name);
2519 notifyUnbound(old, name);
2520 }
2521
2522 @Override
2523 public String[] getValueNames() {
2524 return keyValueStorage.keySet().toArray(EMPTY_STRINGS);
2525 }
2526
2527 private void notifyUnbound(Object value, String name) {
2528 if (value instanceof SSLSessionBindingListener) {
2529
2530 ((SSLSessionBindingListener) value).valueUnbound(newSSLSessionBindingEvent(name));
2531 }
2532 }
2533
2534
2535
2536
2537
2538 @Override
2539 public void handshakeFinished(byte[] id, String cipher, String protocol, byte[] peerCertificate,
2540 byte[][] peerCertificateChain, long creationTime, long timeout)
2541 throws SSLException {
2542 synchronized (ReferenceCountedOpenSslEngine.this) {
2543 if (!destroyed) {
2544 if (this.id == OpenSslSessionId.NULL_ID) {
2545
2546
2547 this.id = id == null ? OpenSslSessionId.NULL_ID : new OpenSslSessionId(id);
2548
2549
2550 this.creationTime = lastAccessed = creationTime;
2551 }
2552 this.cipher = toJavaCipherSuite(cipher);
2553 this.protocol = protocol;
2554
2555 if (clientMode) {
2556 if (isEmpty(peerCertificateChain)) {
2557 peerCerts = EmptyArrays.EMPTY_CERTIFICATES;
2558 if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) {
2559 x509PeerCerts = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
2560 } else {
2561 x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED;
2562 }
2563 } else {
2564 peerCerts = new Certificate[peerCertificateChain.length];
2565 if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) {
2566 x509PeerCerts = new X509Certificate[peerCertificateChain.length];
2567 } else {
2568 x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED;
2569 }
2570 initCerts(peerCertificateChain, 0);
2571 }
2572 } else {
2573
2574
2575
2576
2577
2578 if (isEmpty(peerCertificate)) {
2579 peerCerts = EmptyArrays.EMPTY_CERTIFICATES;
2580 x509PeerCerts = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
2581 } else {
2582 if (isEmpty(peerCertificateChain)) {
2583 peerCerts = new Certificate[] {new LazyX509Certificate(peerCertificate)};
2584 if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) {
2585 x509PeerCerts = new X509Certificate[] {
2586 new LazyJavaxX509Certificate(peerCertificate)
2587 };
2588 } else {
2589 x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED;
2590 }
2591 } else {
2592 peerCerts = new Certificate[peerCertificateChain.length + 1];
2593 peerCerts[0] = new LazyX509Certificate(peerCertificate);
2594
2595 if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) {
2596 x509PeerCerts = new X509Certificate[peerCertificateChain.length + 1];
2597 x509PeerCerts[0] = new LazyJavaxX509Certificate(peerCertificate);
2598 } else {
2599 x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED;
2600 }
2601
2602 initCerts(peerCertificateChain, 1);
2603 }
2604 }
2605 }
2606
2607 calculateMaxWrapOverhead();
2608
2609 handshakeState = HandshakeState.FINISHED;
2610 } else {
2611 throw new SSLException("Already closed");
2612 }
2613 }
2614 }
2615
2616 private void initCerts(byte[][] chain, int startPos) {
2617 for (int i = 0; i < chain.length; i++) {
2618 int certPos = startPos + i;
2619 peerCerts[certPos] = new LazyX509Certificate(chain[i]);
2620 if (x509PeerCerts != JAVAX_CERTS_NOT_SUPPORTED) {
2621 x509PeerCerts[certPos] = new LazyJavaxX509Certificate(chain[i]);
2622 }
2623 }
2624 }
2625
2626 @Override
2627 public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
2628 synchronized (ReferenceCountedOpenSslEngine.this) {
2629 if (isEmpty(peerCerts)) {
2630 throw new SSLPeerUnverifiedException("peer not verified");
2631 }
2632 return peerCerts.clone();
2633 }
2634 }
2635
2636 @Override
2637 public boolean hasPeerCertificates() {
2638 synchronized (ReferenceCountedOpenSslEngine.this) {
2639 return !isEmpty(peerCerts);
2640 }
2641 }
2642
2643 @Override
2644 public Certificate[] getLocalCertificates() {
2645 Certificate[] localCerts = localCertificateChain;
2646 if (localCerts == null) {
2647 return null;
2648 }
2649 return localCerts.clone();
2650 }
2651
2652 @Override
2653 public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException {
2654 synchronized (ReferenceCountedOpenSslEngine.this) {
2655 if (x509PeerCerts == JAVAX_CERTS_NOT_SUPPORTED) {
2656
2657
2658 throw new UnsupportedOperationException();
2659 }
2660 if (isEmpty(x509PeerCerts)) {
2661 throw new SSLPeerUnverifiedException("peer not verified");
2662 }
2663 return x509PeerCerts.clone();
2664 }
2665 }
2666
2667 @Override
2668 public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
2669 Certificate[] peer = getPeerCertificates();
2670
2671
2672 return ((java.security.cert.X509Certificate) peer[0]).getSubjectX500Principal();
2673 }
2674
2675 @Override
2676 public Principal getLocalPrincipal() {
2677 Certificate[] local = localCertificateChain;
2678 if (local == null || local.length == 0) {
2679 return null;
2680 }
2681 return ((java.security.cert.X509Certificate) local[0]).getSubjectX500Principal();
2682 }
2683
2684 @Override
2685 public String getCipherSuite() {
2686 synchronized (ReferenceCountedOpenSslEngine.this) {
2687 if (cipher == null) {
2688 return SslUtils.INVALID_CIPHER;
2689 }
2690 return cipher;
2691 }
2692 }
2693
2694 @Override
2695 public String getProtocol() {
2696 String protocol = this.protocol;
2697 if (protocol == null) {
2698 synchronized (ReferenceCountedOpenSslEngine.this) {
2699 if (!destroyed) {
2700 protocol = SSL.getVersion(ssl);
2701 } else {
2702 protocol = StringUtil.EMPTY_STRING;
2703 }
2704 }
2705 }
2706 return protocol;
2707 }
2708
2709 @Override
2710 public String getPeerHost() {
2711 return ReferenceCountedOpenSslEngine.this.getPeerHost();
2712 }
2713
2714 @Override
2715 public int getPeerPort() {
2716 return ReferenceCountedOpenSslEngine.this.getPeerPort();
2717 }
2718
2719 @Override
2720 public int getPacketBufferSize() {
2721 return SSL.SSL_MAX_ENCRYPTED_LENGTH;
2722 }
2723
2724 @Override
2725 public int getApplicationBufferSize() {
2726 return applicationBufferSize;
2727 }
2728
2729 @Override
2730 public void tryExpandApplicationBufferSize(int packetLengthDataOnly) {
2731 if (packetLengthDataOnly > MAX_PLAINTEXT_LENGTH && applicationBufferSize != MAX_RECORD_SIZE) {
2732 applicationBufferSize = MAX_RECORD_SIZE;
2733 }
2734 }
2735
2736 @Override
2737 public String toString() {
2738 return "DefaultOpenSslSession{" +
2739 "sessionContext=" + sessionContext +
2740 ", id=" + id +
2741 '}';
2742 }
2743
2744 @Override
2745 public int hashCode() {
2746 return sessionId().hashCode();
2747 }
2748
2749 @Override
2750 public boolean equals(Object o) {
2751 if (o == this) {
2752 return true;
2753 }
2754
2755 if (!(o instanceof OpenSslInternalSession)) {
2756 return false;
2757 }
2758 return sessionId().equals(((OpenSslInternalSession) o).sessionId());
2759 }
2760 }
2761
2762 private interface NativeSslException {
2763 int errorCode();
2764 }
2765
2766 private static final class OpenSslException extends SSLException implements NativeSslException {
2767 private final int errorCode;
2768
2769 OpenSslException(String reason, int errorCode) {
2770 super(reason);
2771 this.errorCode = errorCode;
2772 }
2773
2774 @Override
2775 public int errorCode() {
2776 return errorCode;
2777 }
2778 }
2779
2780 private static final class OpenSslHandshakeException extends SSLHandshakeException implements NativeSslException {
2781 private final int errorCode;
2782
2783 OpenSslHandshakeException(String reason, int errorCode) {
2784 super(reason);
2785 this.errorCode = errorCode;
2786 }
2787
2788 @Override
2789 public int errorCode() {
2790 return errorCode;
2791 }
2792 }
2793 }