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