• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * Copyright 2016 The Netty Project
19  *
20  * The Netty Project licenses this file to you under the Apache License,
21  * version 2.0 (the "License"); you may not use this file except in compliance
22  * with the License. You may obtain a copy of the License at:
23  *
24  *   http://www.apache.org/licenses/LICENSE-2.0
25  *
26  * Unless required by applicable law or agreed to in writing, software
27  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29  * License for the specific language governing permissions and limitations
30  * under the License.
31  */
32 
33 package org.conscrypt;
34 
35 import static java.lang.Math.max;
36 import static java.lang.Math.min;
37 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.FINISHED;
38 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
39 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_WRAP;
40 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
41 import static javax.net.ssl.SSLEngineResult.Status.BUFFER_OVERFLOW;
42 import static javax.net.ssl.SSLEngineResult.Status.BUFFER_UNDERFLOW;
43 import static javax.net.ssl.SSLEngineResult.Status.CLOSED;
44 import static javax.net.ssl.SSLEngineResult.Status.OK;
45 import static org.conscrypt.NativeConstants.SSL3_RT_HEADER_LENGTH;
46 import static org.conscrypt.NativeConstants.SSL3_RT_MAX_PACKET_SIZE;
47 import static org.conscrypt.NativeConstants.SSL3_RT_MAX_PLAIN_LENGTH;
48 import static org.conscrypt.NativeConstants.SSL_CB_HANDSHAKE_DONE;
49 import static org.conscrypt.NativeConstants.SSL_CB_HANDSHAKE_START;
50 import static org.conscrypt.NativeConstants.SSL_ERROR_WANT_READ;
51 import static org.conscrypt.NativeConstants.SSL_ERROR_WANT_WRITE;
52 import static org.conscrypt.NativeConstants.SSL_ERROR_ZERO_RETURN;
53 import static org.conscrypt.Preconditions.checkArgument;
54 import static org.conscrypt.Preconditions.checkNotNull;
55 import static org.conscrypt.Preconditions.checkPositionIndexes;
56 import static org.conscrypt.SSLUtils.EngineStates.STATE_CLOSED;
57 import static org.conscrypt.SSLUtils.EngineStates.STATE_CLOSED_INBOUND;
58 import static org.conscrypt.SSLUtils.EngineStates.STATE_CLOSED_OUTBOUND;
59 import static org.conscrypt.SSLUtils.EngineStates.STATE_HANDSHAKE_COMPLETED;
60 import static org.conscrypt.SSLUtils.EngineStates.STATE_HANDSHAKE_STARTED;
61 import static org.conscrypt.SSLUtils.EngineStates.STATE_MODE_SET;
62 import static org.conscrypt.SSLUtils.EngineStates.STATE_NEW;
63 import static org.conscrypt.SSLUtils.EngineStates.STATE_READY;
64 import static org.conscrypt.SSLUtils.EngineStates.STATE_READY_HANDSHAKE_CUT_THROUGH;
65 import static org.conscrypt.SSLUtils.calculateOutNetBufSize;
66 import static org.conscrypt.SSLUtils.toSSLHandshakeException;
67 
68 import java.io.EOFException;
69 import java.io.IOException;
70 import java.io.InterruptedIOException;
71 import java.nio.ByteBuffer;
72 import java.nio.ReadOnlyBufferException;
73 import java.security.InvalidKeyException;
74 import java.security.PrivateKey;
75 import java.security.cert.CertificateEncodingException;
76 import java.security.cert.CertificateException;
77 import java.security.interfaces.ECKey;
78 import java.security.spec.ECParameterSpec;
79 import javax.crypto.SecretKey;
80 import javax.net.ssl.SSLEngine;
81 import javax.net.ssl.SSLEngineResult;
82 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
83 import javax.net.ssl.SSLEngineResult.Status;
84 import javax.net.ssl.SSLException;
85 import javax.net.ssl.SSLHandshakeException;
86 import javax.net.ssl.SSLParameters;
87 import javax.net.ssl.SSLSession;
88 import javax.net.ssl.X509ExtendedKeyManager;
89 import javax.net.ssl.X509KeyManager;
90 import javax.net.ssl.X509TrustManager;
91 import javax.security.auth.x500.X500Principal;
92 import org.conscrypt.NativeRef.SSL_SESSION;
93 import org.conscrypt.SslWrapper.BioWrapper;
94 
95 /**
96  * Implements the {@link SSLEngine} API using OpenSSL's non-blocking interfaces.
97  */
98 final class ConscryptEngine extends SSLEngine implements NativeCrypto.SSLHandshakeCallbacks,
99                                                          SSLParametersImpl.AliasChooser,
100                                                          SSLParametersImpl.PSKCallbacks {
101     private static final SSLEngineResult NEED_UNWRAP_OK =
102             new SSLEngineResult(OK, NEED_UNWRAP, 0, 0);
103     private static final SSLEngineResult NEED_UNWRAP_CLOSED =
104             new SSLEngineResult(CLOSED, NEED_UNWRAP, 0, 0);
105     private static final SSLEngineResult NEED_WRAP_OK = new SSLEngineResult(OK, NEED_WRAP, 0, 0);
106     private static final SSLEngineResult NEED_WRAP_CLOSED =
107             new SSLEngineResult(CLOSED, NEED_WRAP, 0, 0);
108     private static final SSLEngineResult CLOSED_NOT_HANDSHAKING =
109             new SSLEngineResult(CLOSED, NOT_HANDSHAKING, 0, 0);
110     private static final ByteBuffer EMPTY = ByteBuffer.allocateDirect(0);
111 
112     private final SSLParametersImpl sslParameters;
113     private BufferAllocator bufferAllocator;
114 
115     /**
116      * A lazy-created direct buffer used as a bridge between heap buffers provided by the
117      * application and JNI. This avoids the overhead of calling JNI with heap buffers.
118      * Used only when no {@link #bufferAllocator} has been provided.
119      */
120     private ByteBuffer lazyDirectBuffer;
121 
122     /**
123      * Hostname used with the TLS extension SNI hostname.
124      */
125     private String peerHostname;
126 
127     /**
128      * Protects {@link #state} and {@link #handshakeFinished}.
129      */
130     private final Object stateLock = new Object();
131 
132     // @GuardedBy("stateLock");
133     private int state = STATE_NEW;
134     private boolean handshakeFinished;
135 
136     /**
137      * Protected by synchronizing on stateLock. Starts as 0, set by startHandshake, reset to 0 on
138      * close.
139      */
140     // @GuardedBy("stateLock");
141     private final SslWrapper ssl;
142 
143     /**
144      * The BIO used for reading/writing encrypted bytes.
145      */
146     // @GuardedBy("stateLock");
147     private final BioWrapper networkBio;
148 
149     /**
150      * Set during startHandshake.
151      */
152     private final ActiveSession sslSession;
153 
154     /**
155      * Private key for the TLS Channel ID extension. This field is client-side only. Set during
156      * startHandshake.
157      */
158     private OpenSSLKey channelIdPrivateKey;
159 
160     private int maxSealOverhead;
161 
162     private HandshakeListener handshakeListener;
163 
164     private final ByteBuffer[] singleSrcBuffer = new ByteBuffer[1];
165     private final ByteBuffer[] singleDstBuffer = new ByteBuffer[1];
166     private final PeerInfoProvider peerInfoProvider;
167 
168     private SSLException handshakeException;
169 
ConscryptEngine(SSLParametersImpl sslParameters)170     ConscryptEngine(SSLParametersImpl sslParameters) {
171         this.sslParameters = sslParameters;
172         peerInfoProvider = PeerInfoProvider.nullProvider();
173         this.ssl = newSsl(sslParameters, this);
174         this.networkBio = ssl.newBio();
175         sslSession = new ActiveSession(ssl, sslParameters.getSessionContext());
176     }
177 
ConscryptEngine(String host, int port, SSLParametersImpl sslParameters)178     ConscryptEngine(String host, int port, SSLParametersImpl sslParameters) {
179         this.sslParameters = sslParameters;
180         this.peerInfoProvider = PeerInfoProvider.forHostAndPort(host, port);
181         this.ssl = newSsl(sslParameters, this);
182         this.networkBio = ssl.newBio();
183         sslSession = new ActiveSession(ssl, sslParameters.getSessionContext());
184     }
185 
ConscryptEngine(SSLParametersImpl sslParameters, PeerInfoProvider peerInfoProvider)186     ConscryptEngine(SSLParametersImpl sslParameters, PeerInfoProvider peerInfoProvider) {
187         this.sslParameters = sslParameters;
188         this.peerInfoProvider = checkNotNull(peerInfoProvider, "peerInfoProvider");
189         this.ssl = newSsl(sslParameters, this);
190         this.networkBio = ssl.newBio();
191         sslSession = new ActiveSession(ssl, sslParameters.getSessionContext());
192     }
193 
newSsl(SSLParametersImpl sslParameters, ConscryptEngine engine)194     private static SslWrapper newSsl(SSLParametersImpl sslParameters, ConscryptEngine engine) {
195         try {
196             return SslWrapper.newInstance(sslParameters, engine, engine, engine);
197         } catch (SSLException e) {
198             throw new RuntimeException(e);
199         }
200     }
201 
setBufferAllocator(BufferAllocator bufferAllocator)202     void setBufferAllocator(BufferAllocator bufferAllocator) {
203         synchronized (stateLock) {
204             if (isHandshakeStarted()) {
205                 throw new IllegalStateException(
206                         "Could not set buffer allocator after the initial handshake has begun.");
207             }
208             this.bufferAllocator = bufferAllocator;
209         }
210     }
211 
212     /**
213      * Returns the maximum overhead, in bytes, of sealing a record with SSL.
214      */
maxSealOverhead()215     int maxSealOverhead() {
216         return maxSealOverhead;
217     }
218 
219     /**
220      * Enables/disables TLS Channel ID for this server engine.
221      *
222      * <p>This method needs to be invoked before the handshake starts.
223      *
224      * @throws IllegalStateException if this is a client engine or if the handshake has already
225      *         started.
226      */
setChannelIdEnabled(boolean enabled)227     void setChannelIdEnabled(boolean enabled) {
228         synchronized (stateLock) {
229             if (getUseClientMode()) {
230                 throw new IllegalStateException("Not allowed in client mode");
231             }
232             if (isHandshakeStarted()) {
233                 throw new IllegalStateException(
234                         "Could not enable/disable Channel ID after the initial handshake has begun.");
235             }
236             sslParameters.channelIdEnabled = enabled;
237         }
238     }
239 
240     /**
241      * Gets the TLS Channel ID for this server engine. Channel ID is only available once the
242      * handshake completes.
243      *
244      * @return channel ID or {@code null} if not available.
245      *
246      * @throws IllegalStateException if this is a client engine or if the handshake has not yet
247      * completed.
248      * @throws SSLException if channel ID is available but could not be obtained.
249      */
getChannelId()250     byte[] getChannelId() throws SSLException {
251         synchronized (stateLock) {
252             if (getUseClientMode()) {
253                 throw new IllegalStateException("Not allowed in client mode");
254             }
255 
256             if (isHandshakeStarted()) {
257                 throw new IllegalStateException(
258                         "Channel ID is only available after handshake completes");
259             }
260             return ssl.getTlsChannelId();
261         }
262     }
263 
264     /**
265      * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client engine.
266      *
267      * <p>This method needs to be invoked before the handshake starts.
268      *
269      * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables
270      *        TLS Channel ID). The private key must be an Elliptic Curve (EC) key based on the NIST
271      *        P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1).
272      *
273      * @throws IllegalStateException if this is a server engine or if the handshake has already
274      *         started.
275      */
setChannelIdPrivateKey(PrivateKey privateKey)276     void setChannelIdPrivateKey(PrivateKey privateKey) {
277         if (!getUseClientMode()) {
278             throw new IllegalStateException("Not allowed in server mode");
279         }
280 
281         synchronized (stateLock) {
282             if (isHandshakeStarted()) {
283                 throw new IllegalStateException("Could not change Channel ID private key "
284                         + "after the initial handshake has begun.");
285             }
286 
287             if (privateKey == null) {
288                 sslParameters.channelIdEnabled = false;
289                 channelIdPrivateKey = null;
290                 return;
291             }
292 
293             sslParameters.channelIdEnabled = true;
294             try {
295                 ECParameterSpec ecParams = null;
296                 if (privateKey instanceof ECKey) {
297                     ecParams = ((ECKey) privateKey).getParams();
298                 }
299                 if (ecParams == null) {
300                     // Assume this is a P-256 key, as specified in the contract of this method.
301                     ecParams =
302                             OpenSSLECGroupContext.getCurveByName("prime256v1").getECParameterSpec();
303                 }
304                 channelIdPrivateKey =
305                         OpenSSLKey.fromECPrivateKeyForTLSStackOnly(privateKey, ecParams);
306             } catch (InvalidKeyException e) {
307                 // Will have error in startHandshake
308             }
309         }
310     }
311 
312     /**
313      * Sets the listener for the completion of the TLS handshake.
314      */
setHandshakeListener(HandshakeListener handshakeListener)315     void setHandshakeListener(HandshakeListener handshakeListener) {
316         synchronized (stateLock) {
317             if (isHandshakeStarted()) {
318                 throw new IllegalStateException(
319                         "Handshake listener must be set before starting the handshake.");
320             }
321             this.handshakeListener = handshakeListener;
322         }
323     }
324 
isHandshakeStarted()325     private boolean isHandshakeStarted() {
326         switch (state) {
327             case STATE_NEW:
328             case STATE_MODE_SET:
329                 return false;
330             default:
331                 return true;
332         }
333     }
334 
335     /**
336      * This method enables Server Name Indication (SNI) and overrides the {@link PeerInfoProvider}
337      * supplied during engine creation.
338      */
setHostname(String hostname)339     void setHostname(String hostname) {
340         sslParameters.setUseSni(hostname != null);
341         this.peerHostname = hostname;
342     }
343 
344     /**
345      * Returns the hostname from {@link #setHostname(String)} or supplied by the
346      * {@link PeerInfoProvider} upon creation. No DNS resolution is attempted before
347      * returning the hostname.
348      */
getHostname()349     String getHostname() {
350         return peerHostname != null ? peerHostname : peerInfoProvider.getHostname();
351     }
352 
353     @Override
getPeerHost()354     public String getPeerHost() {
355         return peerHostname != null ? peerHostname : peerInfoProvider.getHostnameOrIP();
356     }
357 
358     @Override
getPeerPort()359     public int getPeerPort() {
360         return peerInfoProvider.getPort();
361     }
362 
363     @Override
beginHandshake()364     public void beginHandshake() throws SSLException {
365         synchronized (stateLock) {
366             beginHandshakeInternal();
367         }
368     }
369 
beginHandshakeInternal()370     private void beginHandshakeInternal() throws SSLException {
371         switch (state) {
372             case STATE_MODE_SET:
373                 // This is the only allowed state.
374                 break;
375             case STATE_HANDSHAKE_STARTED:
376                 throw new IllegalStateException("Handshake has already been started");
377             case STATE_CLOSED_INBOUND:
378             case STATE_CLOSED_OUTBOUND:
379             case STATE_CLOSED:
380                 throw new IllegalStateException("Engine has already been closed");
381             default:
382                 throw new IllegalStateException("Client/server mode must be set before handshake");
383         }
384 
385         state = STATE_HANDSHAKE_STARTED;
386 
387         boolean releaseResources = true;
388         try {
389             // Prepare the SSL object for the handshake.
390             ssl.initialize(getHostname(), channelIdPrivateKey);
391 
392             // For clients, offer to resume a previously cached session to avoid the
393             // full TLS handshake.
394             if (getUseClientMode()) {
395                 SslSessionWrapper cachedSession = clientSessionContext().getCachedSession(
396                         getHostname(), getPeerPort(), sslParameters);
397                 if (cachedSession != null) {
398                     cachedSession.offerToResume(ssl);
399                 }
400             }
401 
402             maxSealOverhead = ssl.getMaxSealOverhead();
403             handshake();
404             releaseResources = false;
405         } catch (IOException e) {
406             // Write CCS errors to EventLog
407             String message = e.getMessage();
408             // Must match error reason string of SSL_R_UNEXPECTED_CCS (in ssl/ssl_err.c)
409             if (message.contains("unexpected CCS")) {
410                 String logMessage = String.format("ssl_unexpected_ccs: host=%s", getPeerHost());
411                 Platform.logEvent(logMessage);
412             }
413             throw SSLUtils.toSSLHandshakeException(e);
414         } finally {
415             if (releaseResources) {
416                 state = STATE_CLOSED;
417                 shutdownAndFreeSslNative();
418             }
419         }
420     }
421 
422     @Override
closeInbound()423     public void closeInbound() throws SSLException {
424         synchronized (stateLock) {
425             if (state == STATE_CLOSED) {
426                 return;
427             }
428             if (state == STATE_CLOSED_OUTBOUND) {
429                 state = STATE_CLOSED;
430             } else {
431                 state = STATE_CLOSED_INBOUND;
432             }
433         }
434         // TODO anything else to notify OpenSSL layer?
435     }
436 
437     @Override
closeOutbound()438     public void closeOutbound() {
439         synchronized (stateLock) {
440             if (state == STATE_CLOSED || state == STATE_CLOSED_OUTBOUND) {
441                 return;
442             }
443             if (isHandshakeStarted()) {
444                 shutdownAndFreeSslNative();
445             }
446             if (state == STATE_CLOSED_INBOUND) {
447                 state = STATE_CLOSED;
448             } else {
449                 state = STATE_CLOSED_OUTBOUND;
450             }
451         }
452         shutdown();
453     }
454 
455     @Override
getDelegatedTask()456     public Runnable getDelegatedTask() {
457         // This implementation doesn't use any delegated tasks.
458         return null;
459     }
460 
461     @Override
getEnabledCipherSuites()462     public String[] getEnabledCipherSuites() {
463         return sslParameters.getEnabledCipherSuites();
464     }
465 
466     @Override
getEnabledProtocols()467     public String[] getEnabledProtocols() {
468         return sslParameters.getEnabledProtocols();
469     }
470 
471     @Override
getEnableSessionCreation()472     public boolean getEnableSessionCreation() {
473         return sslParameters.getEnableSessionCreation();
474     }
475 
476     @Override
getSSLParameters()477     public SSLParameters getSSLParameters() {
478         SSLParameters params = super.getSSLParameters();
479         Platform.getSSLParameters(params, sslParameters, this);
480         return params;
481     }
482 
483     @Override
setSSLParameters(SSLParameters p)484     public void setSSLParameters(SSLParameters p) {
485         super.setSSLParameters(p);
486         Platform.setSSLParameters(p, sslParameters, this);
487     }
488 
489     @Override
getHandshakeStatus()490     public HandshakeStatus getHandshakeStatus() {
491         synchronized (stateLock) {
492             return getHandshakeStatusInternal();
493         }
494     }
495 
getHandshakeStatusInternal()496     private HandshakeStatus getHandshakeStatusInternal() {
497         if (handshakeFinished) {
498             return HandshakeStatus.NOT_HANDSHAKING;
499         }
500         switch (state) {
501             case STATE_HANDSHAKE_STARTED:
502                 return pendingStatus(pendingOutboundEncryptedBytes());
503             case STATE_HANDSHAKE_COMPLETED:
504                 return HandshakeStatus.NEED_WRAP;
505             case STATE_NEW:
506             case STATE_MODE_SET:
507             case STATE_CLOSED:
508             case STATE_CLOSED_INBOUND:
509             case STATE_CLOSED_OUTBOUND:
510             case STATE_READY:
511             case STATE_READY_HANDSHAKE_CUT_THROUGH:
512                 return HandshakeStatus.NOT_HANDSHAKING;
513             default:
514                 break;
515         }
516         throw new IllegalStateException("Unexpected engine state: " + state);
517     }
518 
pendingOutboundEncryptedBytes()519     private int pendingOutboundEncryptedBytes() {
520         return networkBio.getPendingWrittenBytes();
521     }
522 
pendingInboundCleartextBytes()523     private int pendingInboundCleartextBytes() {
524         return ssl.getPendingReadableBytes();
525     }
526 
pendingStatus(int pendingOutboundBytes)527     private static SSLEngineResult.HandshakeStatus pendingStatus(int pendingOutboundBytes) {
528         // Depending on if there is something left in the BIO we need to WRAP or UNWRAP
529         return pendingOutboundBytes > 0 ? NEED_WRAP : NEED_UNWRAP;
530     }
531 
532     @Override
getNeedClientAuth()533     public boolean getNeedClientAuth() {
534         return sslParameters.getNeedClientAuth();
535     }
536 
537     /* @Override */
538     @SuppressWarnings("MissingOverride") // For compilation with Java 6.
getHandshakeSession()539     public SSLSession getHandshakeSession() {
540         return handshakeSession();
541     }
542 
543     /**
544      * Work-around to allow this method to be called on older versions of Android.
545      */
handshakeSession()546     SSLSession handshakeSession() {
547         synchronized (stateLock) {
548             return state == STATE_HANDSHAKE_STARTED ? sslSession : null;
549         }
550     }
551 
552     @Override
getSession()553     public SSLSession getSession() {
554         synchronized (stateLock) {
555             if (state < STATE_HANDSHAKE_COMPLETED) {
556                 // Return an invalid session with invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
557                 return SSLNullSession.getNullSession();
558             }
559             return Platform.wrapSSLSession(sslSession);
560         }
561     }
562 
563     @Override
getSupportedCipherSuites()564     public String[] getSupportedCipherSuites() {
565         return NativeCrypto.getSupportedCipherSuites();
566     }
567 
568     @Override
getSupportedProtocols()569     public String[] getSupportedProtocols() {
570         return NativeCrypto.getSupportedProtocols();
571     }
572 
573     @Override
getUseClientMode()574     public boolean getUseClientMode() {
575         return sslParameters.getUseClientMode();
576     }
577 
578     @Override
getWantClientAuth()579     public boolean getWantClientAuth() {
580         return sslParameters.getWantClientAuth();
581     }
582 
583     @Override
isInboundDone()584     public boolean isInboundDone() {
585         synchronized (stateLock) {
586             if (state == STATE_CLOSED || state == STATE_CLOSED_INBOUND) {
587                 return true;
588             }
589         }
590         return ssl.wasShutdownReceived();
591     }
592 
593     @Override
isOutboundDone()594     public boolean isOutboundDone() {
595         synchronized (stateLock) {
596             if (state == STATE_CLOSED || state == STATE_CLOSED_OUTBOUND) {
597                 return true;
598             }
599         }
600         return ssl.wasShutdownSent();
601     }
602 
603     @Override
setEnabledCipherSuites(String[] suites)604     public void setEnabledCipherSuites(String[] suites) {
605         sslParameters.setEnabledCipherSuites(suites);
606     }
607 
608     @Override
setEnabledProtocols(String[] protocols)609     public void setEnabledProtocols(String[] protocols) {
610         sslParameters.setEnabledProtocols(protocols);
611     }
612 
613     @Override
setEnableSessionCreation(boolean flag)614     public void setEnableSessionCreation(boolean flag) {
615         sslParameters.setEnableSessionCreation(flag);
616     }
617 
618     @Override
setNeedClientAuth(boolean need)619     public void setNeedClientAuth(boolean need) {
620         sslParameters.setNeedClientAuth(need);
621     }
622 
623     @Override
setUseClientMode(boolean mode)624     public void setUseClientMode(boolean mode) {
625         synchronized (stateLock) {
626             if (isHandshakeStarted()) {
627                 throw new IllegalArgumentException(
628                         "Can not change mode after handshake: state == " + state);
629             }
630             state = STATE_MODE_SET;
631         }
632         sslParameters.setUseClientMode(mode);
633     }
634 
635     @Override
setWantClientAuth(boolean want)636     public void setWantClientAuth(boolean want) {
637         sslParameters.setWantClientAuth(want);
638     }
639 
640     @Override
unwrap(ByteBuffer src, ByteBuffer dst)641     public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
642         synchronized (stateLock) {
643             try {
644                 return unwrap(singleSrcBuffer(src), singleDstBuffer(dst));
645             } finally {
646                 resetSingleSrcBuffer();
647                 resetSingleDstBuffer();
648             }
649         }
650     }
651 
652     @Override
unwrap(ByteBuffer src, ByteBuffer[] dsts)653     public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException {
654         synchronized (stateLock) {
655             try {
656                 return unwrap(singleSrcBuffer(src), dsts);
657             } finally {
658                 resetSingleSrcBuffer();
659             }
660         }
661     }
662 
663     @Override
unwrap(final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length)664     public SSLEngineResult unwrap(final ByteBuffer src, final ByteBuffer[] dsts, final int offset,
665             final int length) throws SSLException {
666         synchronized (stateLock) {
667             try {
668                 return unwrap(singleSrcBuffer(src), 0, 1, dsts, offset, length);
669             } finally {
670                 resetSingleSrcBuffer();
671             }
672         }
673     }
674 
unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts)675     SSLEngineResult unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts) throws SSLException {
676         checkArgument(srcs != null, "srcs is null");
677         checkArgument(dsts != null, "dsts is null");
678         return unwrap(srcs, 0, srcs.length, dsts, 0, dsts.length);
679     }
680 
unwrap(final ByteBuffer[] srcs, int srcsOffset, final int srcsLength, final ByteBuffer[] dsts, final int dstsOffset, final int dstsLength)681     SSLEngineResult unwrap(final ByteBuffer[] srcs, int srcsOffset, final int srcsLength,
682             final ByteBuffer[] dsts, final int dstsOffset, final int dstsLength)
683             throws SSLException {
684         checkArgument(srcs != null, "srcs is null");
685         checkArgument(dsts != null, "dsts is null");
686         checkPositionIndexes(srcsOffset, srcsOffset + srcsLength, srcs.length);
687         checkPositionIndexes(dstsOffset, dstsOffset + dstsLength, dsts.length);
688 
689         // Determine the output capacity.
690         final int dstLength = calcDstsLength(dsts, dstsOffset, dstsLength);
691         final int endOffset = dstsOffset + dstsLength;
692 
693         final int srcsEndOffset = srcsOffset + srcsLength;
694         final long srcLength = calcSrcsLength(srcs, srcsOffset, srcsEndOffset);
695 
696         synchronized (stateLock) {
697             switch (state) {
698                 case STATE_MODE_SET:
699                     // Begin the handshake implicitly.
700                     beginHandshakeInternal();
701                     break;
702                 case STATE_CLOSED_INBOUND:
703                 case STATE_CLOSED:
704                     // If the inbound direction is closed. we can't send anymore.
705                     return new SSLEngineResult(Status.CLOSED, getHandshakeStatusInternal(), 0, 0);
706                 case STATE_NEW:
707                     throw new IllegalStateException(
708                             "Client/server mode must be set before calling unwrap");
709                 default:
710                     break;
711             }
712 
713             HandshakeStatus handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
714             if (!handshakeFinished) {
715                 handshakeStatus = handshake();
716                 if (handshakeStatus == NEED_WRAP) {
717                     return NEED_WRAP_OK;
718                 }
719                 if (state == STATE_CLOSED) {
720                     return NEED_WRAP_CLOSED;
721                 }
722                 // NEED_UNWRAP - just fall through to perform the unwrap.
723             }
724 
725             // Consume any source data. Skip this if there are unread cleartext data.
726             boolean noCleartextDataAvailable = pendingInboundCleartextBytes() <= 0;
727             int lenRemaining = 0;
728             if (srcLength > 0 && noCleartextDataAvailable) {
729                 if (srcLength < SSL3_RT_HEADER_LENGTH) {
730                     // Need to be able to read a full TLS header.
731                     return new SSLEngineResult(BUFFER_UNDERFLOW, getHandshakeStatus(), 0, 0);
732                 }
733 
734                 int packetLength = SSLUtils.getEncryptedPacketLength(srcs, srcsOffset);
735                 if (packetLength < 0) {
736                     throw new SSLException("Unable to parse TLS packet header");
737                 }
738 
739                 if (srcLength < packetLength) {
740                     // We either have not enough data to read the packet header or not enough for
741                     // reading the whole packet.
742                     return new SSLEngineResult(BUFFER_UNDERFLOW, getHandshakeStatus(), 0, 0);
743                 }
744 
745                 // Limit the amount of data to be read to a single packet.
746                 lenRemaining = packetLength;
747             } else if (noCleartextDataAvailable) {
748                 // No pending data and nothing provided as input.  Need more data.
749                 return new SSLEngineResult(BUFFER_UNDERFLOW, getHandshakeStatus(), 0, 0);
750             }
751 
752             // Write all of the encrypted source data to the networkBio
753             int bytesConsumed = 0;
754             if (lenRemaining > 0 && srcsOffset < srcsEndOffset) {
755                 do {
756                     ByteBuffer src = srcs[srcsOffset];
757                     int remaining = src.remaining();
758                     if (remaining == 0) {
759                         // We must skip empty buffers as BIO_write will return 0 if asked to
760                         // write something with length 0.
761                         srcsOffset++;
762                         continue;
763                     }
764                     // Write the source encrypted data to the networkBio.
765                     int written = writeEncryptedData(src, min(lenRemaining, remaining));
766                     if (written > 0) {
767                         bytesConsumed += written;
768                         lenRemaining -= written;
769                         if (lenRemaining == 0) {
770                             // A whole packet has been consumed.
771                             break;
772                         }
773 
774                         if (written == remaining) {
775                             srcsOffset++;
776                         } else {
777                             // We were not able to write everything into the BIO so break the
778                             // write loop as otherwise we will produce an error on the next
779                             // write attempt, which will trigger a SSL.clearError() later.
780                             break;
781                         }
782                     } else {
783                         // BIO_write returned a negative or zero number, this means we could not
784                         // complete the write operation and should retry later.
785                         // We ignore BIO_* errors here as we use in memory BIO anyway and will
786                         // do another SSL_* call later on in which we will produce an exception
787                         // in case of an error
788                         NativeCrypto.SSL_clear_error();
789                         break;
790                     }
791                 } while (srcsOffset < srcsEndOffset);
792             }
793 
794             // Now read any available plaintext data.
795             int bytesProduced = 0;
796             try {
797                 if (dstLength > 0) {
798                     // Write decrypted data to dsts buffers
799                     for (int idx = dstsOffset; idx < endOffset; ++idx) {
800                         ByteBuffer dst = dsts[idx];
801                         if (!dst.hasRemaining()) {
802                             continue;
803                         }
804 
805                         int bytesRead = readPlaintextData(dst);
806                         if (bytesRead > 0) {
807                             bytesProduced += bytesRead;
808                             if (dst.hasRemaining()) {
809                                 // We haven't filled this buffer fully, break out of the loop
810                                 // and determine the correct response status below.
811                                 break;
812                             }
813                         } else {
814                             switch (bytesRead) {
815                                 case -SSL_ERROR_WANT_READ:
816                                 case -SSL_ERROR_WANT_WRITE: {
817                                     return newResult(bytesConsumed, bytesProduced, handshakeStatus);
818                                 }
819                                 default: {
820                                     // Should never get here.
821                                     throw shutdownWithError("SSL_read");
822                                 }
823                             }
824                         }
825                     }
826                 } else {
827                     // If the capacity of all destination buffers is 0 we need to trigger a SSL_read
828                     // anyway to ensure everything is flushed in the BIO pair and so we can detect
829                     // it in the pendingInboundCleartextBytes() call.
830                     readPlaintextData(EMPTY);
831                 }
832             } catch (SSLException e) {
833                 if (pendingOutboundEncryptedBytes() > 0) {
834                     // We need to flush any pending bytes to the remote endpoint in case
835                     // there is an alert that needs to be propagated.
836                     if (!handshakeFinished && handshakeException == null) {
837                         // Save the handshake exception. We will re-throw during the next
838                         // handshake.
839                         handshakeException = e;
840                     }
841                     return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced);
842                 }
843 
844                 // Nothing to write, just shutdown and throw the exception.
845                 shutdown();
846                 throw convertException(e);
847             } catch (InterruptedIOException e) {
848                 return newResult(bytesConsumed, bytesProduced, handshakeStatus);
849             } catch (EOFException e) {
850                 closeAll();
851                 throw convertException(e);
852             } catch (IOException e) {
853                 shutdown();
854                 throw convertException(e);
855             }
856 
857             // There won't be any application data until we're done handshaking.
858             // We first check handshakeFinished to eliminate the overhead of extra JNI call if
859             // possible.
860             int pendingCleartextBytes = handshakeFinished ? pendingInboundCleartextBytes() : 0;
861             if (pendingCleartextBytes > 0) {
862                 // We filled all buffers but there is still some data pending in the BIO buffer,
863                 // return BUFFER_OVERFLOW.
864                 return new SSLEngineResult(BUFFER_OVERFLOW,
865                         mayFinishHandshake(handshakeStatus == FINISHED
866                                         ? handshakeStatus
867                                         : getHandshakeStatusInternal()),
868                         bytesConsumed, bytesProduced);
869             }
870 
871             return newResult(bytesConsumed, bytesProduced, handshakeStatus);
872         }
873     }
874 
calcDstsLength(ByteBuffer[] dsts, int dstsOffset, int dstsLength)875     private static int calcDstsLength(ByteBuffer[] dsts, int dstsOffset, int dstsLength) {
876         int capacity = 0;
877         for (int i = 0; i < dsts.length; i++) {
878             ByteBuffer dst = dsts[i];
879             checkArgument(dst != null, "dsts[%d] is null", i);
880             if (dst.isReadOnly()) {
881                 throw new ReadOnlyBufferException();
882             }
883             if (i >= dstsOffset && i < dstsOffset + dstsLength) {
884                 capacity += dst.remaining();
885             }
886         }
887         return capacity;
888     }
889 
calcSrcsLength(ByteBuffer[] srcs, int srcsOffset, int srcsEndOffset)890     private static long calcSrcsLength(ByteBuffer[] srcs, int srcsOffset, int srcsEndOffset) {
891         long len = 0;
892         for (int i = srcsOffset; i < srcsEndOffset; i++) {
893             ByteBuffer src = srcs[i];
894             if (src == null) {
895                 throw new IllegalArgumentException("srcs[" + i + "] is null");
896             }
897             len += src.remaining();
898         }
899         return len;
900     }
901 
handshake()902     private SSLEngineResult.HandshakeStatus handshake() throws SSLException {
903         try {
904             // Only actually perform the handshake if we haven't already just completed it
905             // via BIO operations.
906             try {
907                 // First, check to see if we already have a pending alert that needs to be written.
908                 if (handshakeException != null) {
909                     if (pendingOutboundEncryptedBytes() > 0) {
910                         // Need to finish writing the alert to the remote peer.
911                         return NEED_WRAP;
912                     }
913 
914                     // We've finished writing the alert, just throw the exception.
915                     SSLException e = handshakeException;
916                     handshakeException = null;
917                     throw e;
918                 }
919 
920                 int ssl_error_code = ssl.doHandshake();
921                 switch (ssl_error_code) {
922                     case SSL_ERROR_WANT_READ:
923                         return pendingStatus(pendingOutboundEncryptedBytes());
924                     case SSL_ERROR_WANT_WRITE: {
925                         return NEED_WRAP;
926                     }
927                     default: {
928                         // SSL_ERROR_NONE.
929                     }
930                 }
931             } catch (SSLException e) {
932                 if (pendingOutboundEncryptedBytes() > 0) {
933                     // Delay throwing the exception since we appear to have an outbound alert
934                     // that needs to be written to the remote endpoint.
935                     handshakeException = e;
936                     return NEED_WRAP;
937                 }
938 
939                 // There is no pending alert to write - just shutdown and throw.
940                 shutdown();
941                 throw e;
942             } catch (IOException e) {
943                 shutdown();
944                 throw e;
945             }
946 
947             // The handshake has completed successfully...
948 
949             // Update the session from the current state of the SSL object.
950             sslSession.onSessionEstablished(getPeerHost(), getPeerPort());
951 
952             finishHandshake();
953             return FINISHED;
954         } catch (Exception e) {
955             throw toSSLHandshakeException(e);
956         }
957     }
958 
finishHandshake()959     private void finishHandshake() throws SSLException {
960         handshakeFinished = true;
961         // Notify the listener, if provided.
962         if (handshakeListener != null) {
963             handshakeListener.onHandshakeFinished();
964         }
965     }
966 
967     /**
968      * Write plaintext data to the OpenSSL internal BIO
969      *
970      * Calling this function with src.remaining == 0 is undefined.
971      */
writePlaintextData(final ByteBuffer src, int len)972     private int writePlaintextData(final ByteBuffer src, int len) throws SSLException {
973         try {
974             final int pos = src.position();
975             final int sslWrote;
976             if (src.isDirect()) {
977                 sslWrote = writePlaintextDataDirect(src, pos, len);
978             } else {
979                 sslWrote = writePlaintextDataHeap(src, pos, len);
980             }
981             if (sslWrote > 0) {
982                 src.position(pos + sslWrote);
983             }
984             return sslWrote;
985         } catch (Exception e) {
986             throw convertException(e);
987         }
988     }
989 
writePlaintextDataDirect(ByteBuffer src, int pos, int len)990     private int writePlaintextDataDirect(ByteBuffer src, int pos, int len) throws IOException {
991         return ssl.writeDirectByteBuffer(directByteBufferAddress(src, pos), len);
992     }
993 
writePlaintextDataHeap(ByteBuffer src, int pos, int len)994     private int writePlaintextDataHeap(ByteBuffer src, int pos, int len) throws IOException {
995         AllocatedBuffer allocatedBuffer = null;
996         try {
997             final ByteBuffer buffer;
998             if (bufferAllocator != null) {
999                 allocatedBuffer = bufferAllocator.allocateDirectBuffer(len);
1000                 buffer = allocatedBuffer.nioBuffer();
1001             } else {
1002                 // We don't have a buffer allocator, but we don't want to send a heap
1003                 // buffer to JNI. So lazy-create a direct buffer that we will use from now
1004                 // on to copy plaintext data.
1005                 buffer = getOrCreateLazyDirectBuffer();
1006             }
1007 
1008             // Copy the data to the direct buffer.
1009             int limit = src.limit();
1010             int bytesToWrite = min(len, buffer.remaining());
1011             src.limit(pos + bytesToWrite);
1012             buffer.put(src);
1013             buffer.flip();
1014             // Restore the original position and limit.
1015             src.limit(limit);
1016             src.position(pos);
1017 
1018             return writePlaintextDataDirect(buffer, 0, bytesToWrite);
1019         } finally {
1020             if (allocatedBuffer != null) {
1021                 // Release the buffer back to the pool.
1022                 allocatedBuffer.release();
1023             }
1024         }
1025     }
1026 
1027     /**
1028      * Read plaintext data from the OpenSSL internal BIO
1029      */
readPlaintextData(final ByteBuffer dst)1030     private int readPlaintextData(final ByteBuffer dst) throws IOException {
1031         try {
1032             final int pos = dst.position();
1033             final int limit = dst.limit();
1034             final int len = min(SSL3_RT_MAX_PACKET_SIZE, limit - pos);
1035             if (dst.isDirect()) {
1036                 int bytesRead = readPlaintextDataDirect(dst, pos, len);
1037                 if (bytesRead > 0) {
1038                     dst.position(pos + bytesRead);
1039                 }
1040                 return bytesRead;
1041             }
1042 
1043             // The heap method updates the dst position automatically.
1044             return readPlaintextDataHeap(dst, len);
1045         } catch (CertificateException e) {
1046             throw convertException(e);
1047         }
1048     }
1049 
readPlaintextDataDirect(ByteBuffer dst, int pos, int len)1050     private int readPlaintextDataDirect(ByteBuffer dst, int pos, int len)
1051             throws IOException, CertificateException {
1052         return ssl.readDirectByteBuffer(directByteBufferAddress(dst, pos), len);
1053     }
1054 
readPlaintextDataHeap(ByteBuffer dst, int len)1055     private int readPlaintextDataHeap(ByteBuffer dst, int len)
1056             throws IOException, CertificateException {
1057         AllocatedBuffer allocatedBuffer = null;
1058         try {
1059             final ByteBuffer buffer;
1060             if (bufferAllocator != null) {
1061                 allocatedBuffer = bufferAllocator.allocateDirectBuffer(len);
1062                 buffer = allocatedBuffer.nioBuffer();
1063             } else {
1064                 // We don't have a buffer allocator, but we don't want to send a heap
1065                 // buffer to JNI. So lazy-create a direct buffer that we will use from now
1066                 // on to copy plaintext data.
1067                 buffer = getOrCreateLazyDirectBuffer();
1068             }
1069 
1070             // Read the data to the direct buffer.
1071             int bytesToRead = min(len, buffer.remaining());
1072             int bytesRead = readPlaintextDataDirect(buffer, 0, bytesToRead);
1073             if (bytesRead > 0) {
1074                 // Copy the data to the heap buffer.
1075                 buffer.position(bytesRead);
1076                 buffer.flip();
1077                 dst.put(buffer);
1078             }
1079 
1080             return bytesRead;
1081         } finally {
1082             if (allocatedBuffer != null) {
1083                 // Release the buffer back to the pool.
1084                 allocatedBuffer.release();
1085             }
1086         }
1087     }
1088 
convertException(Throwable e)1089     private SSLException convertException(Throwable e) {
1090         if (e instanceof SSLHandshakeException || !handshakeFinished) {
1091             return SSLUtils.toSSLHandshakeException(e);
1092         }
1093         return SSLUtils.toSSLException(e);
1094     }
1095 
1096     /**
1097      * Write encrypted data to the OpenSSL network BIO.
1098      */
writeEncryptedData(final ByteBuffer src, int len)1099     private int writeEncryptedData(final ByteBuffer src, int len) throws SSLException {
1100         try {
1101             final int pos = src.position();
1102             final int bytesWritten;
1103             if (src.isDirect()) {
1104                 bytesWritten = writeEncryptedDataDirect(src, pos, len);
1105             } else {
1106                 bytesWritten = writeEncryptedDataHeap(src, pos, len);
1107             }
1108 
1109             if (bytesWritten > 0) {
1110                 src.position(pos + bytesWritten);
1111             }
1112 
1113             return bytesWritten;
1114         } catch (IOException e) {
1115             throw new SSLException(e);
1116         }
1117     }
1118 
writeEncryptedDataDirect(ByteBuffer src, int pos, int len)1119     private int writeEncryptedDataDirect(ByteBuffer src, int pos, int len) throws IOException {
1120         return networkBio.writeDirectByteBuffer(directByteBufferAddress(src, pos), len);
1121     }
1122 
writeEncryptedDataHeap(ByteBuffer src, int pos, int len)1123     private int writeEncryptedDataHeap(ByteBuffer src, int pos, int len) throws IOException {
1124         AllocatedBuffer allocatedBuffer = null;
1125         try {
1126             final ByteBuffer buffer;
1127             if (bufferAllocator != null) {
1128                 allocatedBuffer = bufferAllocator.allocateDirectBuffer(len);
1129                 buffer = allocatedBuffer.nioBuffer();
1130             } else {
1131                 // We don't have a buffer allocator, but we don't want to send a heap
1132                 // buffer to JNI. So lazy-create a direct buffer that we will use from now
1133                 // on to copy encrypted packets.
1134                 buffer = getOrCreateLazyDirectBuffer();
1135             }
1136 
1137             int limit = src.limit();
1138             int bytesToCopy = min(min(limit - pos, len), buffer.remaining());
1139             src.limit(pos + bytesToCopy);
1140             buffer.put(src);
1141             // Restore the original limit.
1142             src.limit(limit);
1143 
1144             // Reset the original position on the source buffer.
1145             src.position(pos);
1146 
1147             int bytesWritten = writeEncryptedDataDirect(buffer, 0, bytesToCopy);
1148 
1149             // Restore the original position.
1150             src.position(pos);
1151 
1152             return bytesWritten;
1153         } finally {
1154             if (allocatedBuffer != null) {
1155                 // Release the buffer back to the pool.
1156                 allocatedBuffer.release();
1157             }
1158         }
1159     }
1160 
getOrCreateLazyDirectBuffer()1161     private ByteBuffer getOrCreateLazyDirectBuffer() {
1162         if (lazyDirectBuffer == null) {
1163             lazyDirectBuffer = ByteBuffer.allocateDirect(
1164                     max(SSL3_RT_MAX_PLAIN_LENGTH, SSL3_RT_MAX_PACKET_SIZE));
1165         }
1166         lazyDirectBuffer.clear();
1167         return lazyDirectBuffer;
1168     }
1169 
directByteBufferAddress(ByteBuffer directBuffer, int pos)1170     private long directByteBufferAddress(ByteBuffer directBuffer, int pos) {
1171         return NativeCrypto.getDirectBufferAddress(directBuffer) + pos;
1172     }
1173 
readPendingBytesFromBIO(ByteBuffer dst, int bytesConsumed, int bytesProduced, SSLEngineResult.HandshakeStatus status)1174     private SSLEngineResult readPendingBytesFromBIO(ByteBuffer dst, int bytesConsumed,
1175             int bytesProduced, SSLEngineResult.HandshakeStatus status) throws SSLException {
1176         try {
1177             // Check to see if the engine wrote data into the network BIO
1178             int pendingNet = pendingOutboundEncryptedBytes();
1179             if (pendingNet > 0) {
1180                 // Do we have enough room in dst to write encrypted data?
1181                 int capacity = dst.remaining();
1182                 if (capacity < pendingNet) {
1183                     return new SSLEngineResult(BUFFER_OVERFLOW,
1184                             mayFinishHandshake(
1185                                     status == FINISHED ? status : getHandshakeStatus(pendingNet)),
1186                             bytesConsumed, bytesProduced);
1187                 }
1188 
1189                 // Write the pending data from the network BIO into the dst buffer
1190                 int produced = readEncryptedData(dst, pendingNet);
1191 
1192                 if (produced <= 0) {
1193                     // We ignore BIO_* errors here as we use in memory BIO anyway and will do
1194                     // another SSL_* call later on in which we will produce an exception in
1195                     // case of an error
1196                     NativeCrypto.SSL_clear_error();
1197                 } else {
1198                     bytesProduced += produced;
1199                     pendingNet -= produced;
1200                 }
1201 
1202                 return new SSLEngineResult(getEngineStatus(),
1203                         mayFinishHandshake(
1204                                 status == FINISHED ? status : getHandshakeStatus(pendingNet)),
1205                         bytesConsumed, bytesProduced);
1206             }
1207             return null;
1208         } catch (Exception e) {
1209             throw convertException(e);
1210         }
1211     }
1212 
1213     /**
1214      * Read encrypted data from the OpenSSL network BIO
1215      */
readEncryptedData(final ByteBuffer dst, final int pending)1216     private int readEncryptedData(final ByteBuffer dst, final int pending) throws SSLException {
1217         try {
1218             int bytesRead = 0;
1219             final int pos = dst.position();
1220             if (dst.remaining() >= pending) {
1221                 final int limit = dst.limit();
1222                 final int len = min(pending, limit - pos);
1223                 if (dst.isDirect()) {
1224                     bytesRead = readEncryptedDataDirect(dst, pos, len);
1225                     // Need to update the position on the dst buffer.
1226                     if (bytesRead > 0) {
1227                         dst.position(pos + bytesRead);
1228                     }
1229                 } else {
1230                     // The heap method will update the position on the dst buffer automatically.
1231                     bytesRead = readEncryptedDataHeap(dst, len);
1232                 }
1233             }
1234 
1235             return bytesRead;
1236         } catch (Exception e) {
1237             throw convertException(e);
1238         }
1239     }
1240 
readEncryptedDataDirect(ByteBuffer dst, int pos, int len)1241     private int readEncryptedDataDirect(ByteBuffer dst, int pos, int len) throws IOException {
1242         return networkBio.readDirectByteBuffer(directByteBufferAddress(dst, pos), len);
1243     }
1244 
readEncryptedDataHeap(ByteBuffer dst, int len)1245     private int readEncryptedDataHeap(ByteBuffer dst, int len) throws IOException {
1246         AllocatedBuffer allocatedBuffer = null;
1247         try {
1248             final ByteBuffer buffer;
1249             if (bufferAllocator != null) {
1250                 allocatedBuffer = bufferAllocator.allocateDirectBuffer(len);
1251                 buffer = allocatedBuffer.nioBuffer();
1252             } else {
1253                 // We don't have a buffer allocator, but we don't want to send a heap
1254                 // buffer to JNI. So lazy-create a direct buffer that we will use from now
1255                 // on to copy encrypted packets.
1256                 buffer = getOrCreateLazyDirectBuffer();
1257             }
1258 
1259             int bytesToRead = min(len, buffer.remaining());
1260             int bytesRead = readEncryptedDataDirect(buffer, 0, bytesToRead);
1261             if (bytesRead > 0) {
1262                 buffer.position(bytesRead);
1263                 buffer.flip();
1264                 dst.put(buffer);
1265             }
1266 
1267             return bytesRead;
1268         } finally {
1269             if (allocatedBuffer != null) {
1270                 // Release the buffer back to the pool.
1271                 allocatedBuffer.release();
1272             }
1273         }
1274     }
1275 
mayFinishHandshake( SSLEngineResult.HandshakeStatus status)1276     private SSLEngineResult.HandshakeStatus mayFinishHandshake(
1277             SSLEngineResult.HandshakeStatus status) throws SSLException {
1278         if (!handshakeFinished && status == NOT_HANDSHAKING) {
1279             // If the status was NOT_HANDSHAKING and we not finished the handshake we need to call
1280             // SSL_do_handshake() again
1281             return handshake();
1282         }
1283         return status;
1284     }
1285 
getHandshakeStatus(int pending)1286     private SSLEngineResult.HandshakeStatus getHandshakeStatus(int pending) {
1287         // Check if we are in the initial handshake phase or shutdown phase
1288         return !handshakeFinished ? pendingStatus(pending) : NOT_HANDSHAKING;
1289     }
1290 
getEngineStatus()1291     private SSLEngineResult.Status getEngineStatus() {
1292         switch (state) {
1293             case STATE_CLOSED_INBOUND:
1294             case STATE_CLOSED_OUTBOUND:
1295             case STATE_CLOSED:
1296                 return CLOSED;
1297             default:
1298                 return OK;
1299         }
1300     }
1301 
closeAll()1302     private void closeAll() throws SSLException {
1303         closeOutbound();
1304         closeInbound();
1305     }
1306 
shutdownWithError(String err)1307     private SSLException shutdownWithError(String err) {
1308         // There was an internal error -- shutdown
1309         shutdown();
1310         if (!handshakeFinished) {
1311             return new SSLException(err);
1312         }
1313         return new SSLHandshakeException(err);
1314     }
1315 
newResult(int bytesConsumed, int bytesProduced, SSLEngineResult.HandshakeStatus status)1316     private SSLEngineResult newResult(int bytesConsumed, int bytesProduced,
1317             SSLEngineResult.HandshakeStatus status) throws SSLException {
1318         return new SSLEngineResult(getEngineStatus(),
1319                 mayFinishHandshake(status == FINISHED ? status : getHandshakeStatusInternal()),
1320                 bytesConsumed, bytesProduced);
1321     }
1322 
1323     @Override
wrap(ByteBuffer src, ByteBuffer dst)1324     public final SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1325         synchronized (stateLock) {
1326             try {
1327                 return wrap(singleSrcBuffer(src), dst);
1328             } finally {
1329                 resetSingleSrcBuffer();
1330             }
1331         }
1332     }
1333 
1334     @Override
wrap(ByteBuffer[] srcs, int srcsOffset, int srcsLength, ByteBuffer dst)1335     public SSLEngineResult wrap(ByteBuffer[] srcs, int srcsOffset, int srcsLength, ByteBuffer dst)
1336             throws SSLException {
1337         checkArgument(srcs != null, "srcs is null");
1338         checkArgument(dst != null, "dst is null");
1339         checkPositionIndexes(srcsOffset, srcsOffset + srcsLength, srcs.length);
1340         if (dst.isReadOnly()) {
1341             throw new ReadOnlyBufferException();
1342         }
1343 
1344         synchronized (stateLock) {
1345             switch (state) {
1346                 case STATE_MODE_SET:
1347                     // Begin the handshake implicitly.
1348                     beginHandshakeInternal();
1349                     break;
1350                 case STATE_CLOSED_OUTBOUND:
1351                 case STATE_CLOSED:
1352                     return new SSLEngineResult(Status.CLOSED, getHandshakeStatusInternal(), 0, 0);
1353                 case STATE_NEW:
1354                     throw new IllegalStateException(
1355                             "Client/server mode must be set before calling wrap");
1356                 default:
1357                     break;
1358             }
1359 
1360             // If we haven't completed the handshake yet, just let the caller know.
1361             HandshakeStatus handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
1362             // Prepare OpenSSL to work in server mode and receive handshake
1363             if (!handshakeFinished) {
1364                 handshakeStatus = handshake();
1365                 if (handshakeStatus == NEED_UNWRAP) {
1366                     return NEED_UNWRAP_OK;
1367                 }
1368 
1369                 if (state == STATE_CLOSED) {
1370                     return NEED_UNWRAP_CLOSED;
1371                 }
1372                 // NEED_WRAP - just fall through to perform the wrap.
1373             }
1374 
1375             int srcsLen = 0;
1376             final int endOffset = srcsOffset + srcsLength;
1377             for (int i = srcsOffset; i < endOffset; ++i) {
1378                 final ByteBuffer src = srcs[i];
1379                 if (src == null) {
1380                     throw new IllegalArgumentException("srcs[" + i + "] is null");
1381                 }
1382                 if (srcsLen == SSL3_RT_MAX_PLAIN_LENGTH) {
1383                     continue;
1384                 }
1385 
1386                 srcsLen += src.remaining();
1387                 if (srcsLen > SSL3_RT_MAX_PLAIN_LENGTH || srcsLen < 0) {
1388                     // If srcLen > MAX_PLAINTEXT_LENGTH or secLen < 0 just set it to
1389                     // MAX_PLAINTEXT_LENGTH.
1390                     // This also help us to guard against overflow.
1391                     // We not break out here as we still need to check for null entries in srcs[].
1392                     srcsLen = SSL3_RT_MAX_PLAIN_LENGTH;
1393                 }
1394             }
1395 
1396             if (dst.remaining() < calculateOutNetBufSize(srcsLen)) {
1397                 return new SSLEngineResult(
1398                         Status.BUFFER_OVERFLOW, getHandshakeStatusInternal(), 0, 0);
1399             }
1400 
1401             int bytesProduced = 0;
1402             int bytesConsumed = 0;
1403         loop:
1404             for (int i = srcsOffset; i < endOffset; ++i) {
1405                 final ByteBuffer src = srcs[i];
1406                 checkArgument(src != null, "srcs[%d] is null", i);
1407                 while (src.hasRemaining()) {
1408                     final SSLEngineResult pendingNetResult;
1409                     // Write plaintext application data to the SSL engine
1410                     int result = writePlaintextData(
1411                             src, min(src.remaining(), SSL3_RT_MAX_PLAIN_LENGTH - bytesConsumed));
1412                     if (result > 0) {
1413                         bytesConsumed += result;
1414 
1415                         pendingNetResult = readPendingBytesFromBIO(
1416                                 dst, bytesConsumed, bytesProduced, handshakeStatus);
1417                         if (pendingNetResult != null) {
1418                             if (pendingNetResult.getStatus() != OK) {
1419                                 return pendingNetResult;
1420                             }
1421                             bytesProduced = pendingNetResult.bytesProduced();
1422                         }
1423                         if (bytesConsumed == SSL3_RT_MAX_PLAIN_LENGTH) {
1424                             // If we consumed the maximum amount of bytes for the plaintext length
1425                             // break out of the loop and start to fill the dst buffer.
1426                             break loop;
1427                         }
1428                     } else {
1429                         int sslError = ssl.getError(result);
1430                         switch (sslError) {
1431                             case SSL_ERROR_ZERO_RETURN:
1432                                 // This means the connection was shutdown correctly, close inbound
1433                                 // and outbound
1434                                 closeAll();
1435                                 pendingNetResult = readPendingBytesFromBIO(
1436                                         dst, bytesConsumed, bytesProduced, handshakeStatus);
1437                                 return pendingNetResult != null ? pendingNetResult
1438                                                                 : CLOSED_NOT_HANDSHAKING;
1439                             case SSL_ERROR_WANT_READ:
1440                                 // If there is no pending data to read from BIO we should go back to
1441                                 // event loop and try
1442                                 // to read more data [1]. It is also possible that event loop will
1443                                 // detect the socket
1444                                 // has been closed. [1]
1445                                 // https://www.openssl.org/docs/manmaster/ssl/SSL_write.html
1446                                 pendingNetResult = readPendingBytesFromBIO(
1447                                         dst, bytesConsumed, bytesProduced, handshakeStatus);
1448                                 return pendingNetResult != null
1449                                         ? pendingNetResult
1450                                         : new SSLEngineResult(getEngineStatus(), NEED_UNWRAP,
1451                                                   bytesConsumed, bytesProduced);
1452                             case SSL_ERROR_WANT_WRITE:
1453                                 // SSL_ERROR_WANT_WRITE typically means that the underlying
1454                                 // transport is not writable
1455                                 // and we should set the "want write" flag on the selector and try
1456                                 // again when the
1457                                 // underlying transport is writable [1]. However we are not directly
1458                                 // writing to the
1459                                 // underlying transport and instead writing to a BIO buffer. The
1460                                 // OpenSsl documentation
1461                                 // says we should do the following [1]:
1462                                 //
1463                                 // "When using a buffering BIO, like a BIO pair, data must be
1464                                 // written into or retrieved
1465                                 // out of the BIO before being able to continue."
1466                                 //
1467                                 // So we attempt to drain the BIO buffer below, but if there is no
1468                                 // data this condition
1469                                 // is undefined and we assume their is a fatal error with the
1470                                 // openssl engine and close.
1471                                 // [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html
1472                                 pendingNetResult = readPendingBytesFromBIO(
1473                                         dst, bytesConsumed, bytesProduced, handshakeStatus);
1474                                 return pendingNetResult != null ? pendingNetResult
1475                                                                 : NEED_WRAP_CLOSED;
1476                             default:
1477                                 // Everything else is considered as error
1478                                 throw shutdownWithError("SSL_write");
1479                         }
1480                     }
1481                 }
1482             }
1483             // We need to check if pendingWrittenBytesInBIO was checked yet, as we may not checked
1484             // if the srcs was
1485             // empty, or only contained empty buffers.
1486             if (bytesConsumed == 0) {
1487                 SSLEngineResult pendingNetResult =
1488                         readPendingBytesFromBIO(dst, 0, bytesProduced, handshakeStatus);
1489                 if (pendingNetResult != null) {
1490                     return pendingNetResult;
1491                 }
1492             }
1493 
1494             // return new SSLEngineResult(OK, getHandshakeStatusInternal(), bytesConsumed,
1495             // bytesProduced);
1496             return newResult(bytesConsumed, bytesProduced, handshakeStatus);
1497         }
1498     }
1499 
1500     @Override
clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key)1501     public int clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key) {
1502         return ssl.clientPSKKeyRequested(identityHint, identity, key);
1503     }
1504 
1505     @Override
serverPSKKeyRequested(String identityHint, String identity, byte[] key)1506     public int serverPSKKeyRequested(String identityHint, String identity, byte[] key) {
1507         return ssl.serverPSKKeyRequested(identityHint, identity, key);
1508     }
1509 
1510     @Override
onSSLStateChange(int type, int val)1511     public void onSSLStateChange(int type, int val) {
1512         synchronized (stateLock) {
1513             switch (type) {
1514                 case SSL_CB_HANDSHAKE_START: {
1515                     // For clients, this will allow the NEED_UNWRAP status to be
1516                     // returned.
1517                     state = STATE_HANDSHAKE_STARTED;
1518                     break;
1519                 }
1520                 case SSL_CB_HANDSHAKE_DONE: {
1521                     if (state != STATE_HANDSHAKE_STARTED
1522                             && state != STATE_READY_HANDSHAKE_CUT_THROUGH) {
1523                         throw new IllegalStateException(
1524                                 "Completed handshake while in mode " + state);
1525                     }
1526                     state = STATE_HANDSHAKE_COMPLETED;
1527                     break;
1528                 }
1529             }
1530         }
1531     }
1532 
1533     @Override
onNewSessionEstablished(long sslSessionNativePtr)1534     public void onNewSessionEstablished(long sslSessionNativePtr) {
1535         try {
1536             // Increment the reference count to "take ownership" of the session resource.
1537             NativeCrypto.SSL_SESSION_up_ref(sslSessionNativePtr);
1538 
1539             // Create a native reference which will release the SSL_SESSION in its finalizer.
1540             // This constructor will only throw if the native pointer passed in is NULL, which
1541             // BoringSSL guarantees will not happen.
1542             NativeRef.SSL_SESSION ref = new SSL_SESSION(sslSessionNativePtr);
1543 
1544             SslSessionWrapper sessionWrapper = SslSessionWrapper.newInstance(ref, sslSession);
1545 
1546             // Cache the newly established session.
1547             AbstractSessionContext ctx = sessionContext();
1548             ctx.cacheSession(sessionWrapper);
1549         } catch (Exception ignored) {
1550             // Ignore.
1551         }
1552     }
1553 
1554     @Override
serverSessionRequested(byte[] id)1555     public long serverSessionRequested(byte[] id) {
1556         // TODO(nathanmittler): Implement server-side caching for TLS < 1.3
1557         return 0;
1558     }
1559 
1560     @Override
verifyCertificateChain(long[] certRefs, String authMethod)1561     public void verifyCertificateChain(long[] certRefs, String authMethod)
1562             throws CertificateException {
1563         try {
1564             X509TrustManager x509tm = sslParameters.getX509TrustManager();
1565             if (x509tm == null) {
1566                 throw new CertificateException("No X.509 TrustManager");
1567             }
1568             if (certRefs == null || certRefs.length == 0) {
1569                 throw new SSLException("Peer sent no certificate");
1570             }
1571             OpenSSLX509Certificate[] peerCertChain =
1572                     OpenSSLX509Certificate.createCertChain(certRefs);
1573 
1574             // Update the peer information on the session.
1575             sslSession.onPeerCertificatesReceived(getPeerHost(), getPeerPort(), peerCertChain);
1576 
1577             if (getUseClientMode()) {
1578                 Platform.checkServerTrusted(x509tm, peerCertChain, authMethod, this);
1579             } else {
1580                 String authType = peerCertChain[0].getPublicKey().getAlgorithm();
1581                 Platform.checkClientTrusted(x509tm, peerCertChain, authType, this);
1582             }
1583         } catch (CertificateException e) {
1584             throw e;
1585         } catch (Exception e) {
1586             throw new CertificateException(e);
1587         }
1588     }
1589 
1590     @Override
clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals)1591     public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals)
1592             throws CertificateEncodingException, SSLException {
1593         ssl.chooseClientCertificate(keyTypeBytes, asn1DerEncodedPrincipals);
1594     }
1595 
shutdown()1596     private void shutdown() {
1597         try {
1598             ssl.shutdown();
1599         } catch (IOException ignored) {
1600             // TODO: The RI ignores close failures in SSLSocket, but need to
1601             // investigate whether it does for SSLEngine.
1602         }
1603     }
1604 
shutdownAndFreeSslNative()1605     private void shutdownAndFreeSslNative() {
1606         try {
1607             shutdown();
1608         } finally {
1609             free();
1610         }
1611     }
1612 
free()1613     private void free() {
1614         if (!ssl.isClosed()) {
1615             ssl.close();
1616             networkBio.close();
1617         }
1618     }
1619 
1620     @Override
finalize()1621     protected void finalize() throws Throwable {
1622         try {
1623             free();
1624         } finally {
1625             super.finalize();
1626         }
1627     }
1628 
1629     @Override
chooseServerAlias(X509KeyManager keyManager, String keyType)1630     public String chooseServerAlias(X509KeyManager keyManager, String keyType) {
1631         if (keyManager instanceof X509ExtendedKeyManager) {
1632             X509ExtendedKeyManager ekm = (X509ExtendedKeyManager) keyManager;
1633             return ekm.chooseEngineServerAlias(keyType, null, this);
1634         } else {
1635             return keyManager.chooseServerAlias(keyType, null, null);
1636         }
1637     }
1638 
1639     @Override
chooseClientAlias( X509KeyManager keyManager, X500Principal[] issuers, String[] keyTypes)1640     public String chooseClientAlias(
1641             X509KeyManager keyManager, X500Principal[] issuers, String[] keyTypes) {
1642         if (keyManager instanceof X509ExtendedKeyManager) {
1643             X509ExtendedKeyManager ekm = (X509ExtendedKeyManager) keyManager;
1644             return ekm.chooseEngineClientAlias(keyTypes, issuers, this);
1645         } else {
1646             return keyManager.chooseClientAlias(keyTypes, issuers, null);
1647         }
1648     }
1649 
1650     @Override
1651     @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package
chooseServerPSKIdentityHint(PSKKeyManager keyManager)1652     public String chooseServerPSKIdentityHint(PSKKeyManager keyManager) {
1653         return keyManager.chooseServerKeyIdentityHint(this);
1654     }
1655 
1656     @Override
1657     @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package
chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint)1658     public String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint) {
1659         return keyManager.chooseClientKeyIdentity(identityHint, this);
1660     }
1661 
1662     @Override
1663     @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package
getPSKKey(PSKKeyManager keyManager, String identityHint, String identity)1664     public SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity) {
1665         return keyManager.getKey(identityHint, identity, this);
1666     }
1667 
1668     /**
1669      * This method enables session ticket support.
1670      *
1671      * @param useSessionTickets True to enable session tickets
1672      */
setUseSessionTickets(boolean useSessionTickets)1673     void setUseSessionTickets(boolean useSessionTickets) {
1674         sslParameters.setUseSessionTickets(useSessionTickets);
1675     }
1676 
1677     /**
1678      * Sets the list of ALPN protocols.
1679      *
1680      * @param alpnProtocols the list of ALPN protocols
1681      */
setAlpnProtocols(String[] alpnProtocols)1682     void setAlpnProtocols(String[] alpnProtocols) {
1683         sslParameters.setAlpnProtocols(alpnProtocols);
1684     }
1685 
1686     /**
1687      * Sets the list of ALPN protocols.
1688      *
1689      * @param alpnProtocols the list of ALPN protocols
1690      */
setAlpnProtocols(byte[] alpnProtocols)1691     void setAlpnProtocols(byte[] alpnProtocols) {
1692         sslParameters.setAlpnProtocols(alpnProtocols);
1693     }
1694 
1695     /**
1696      * Returns the protocol agreed upon by client and server, or {@code null} if no protocol was
1697      * agreed upon.
1698      */
getAlpnSelectedProtocol()1699     byte[] getAlpnSelectedProtocol() {
1700         return ssl.getAlpnSelectedProtocol();
1701     }
1702 
singleSrcBuffer(ByteBuffer src)1703     private ByteBuffer[] singleSrcBuffer(ByteBuffer src) {
1704         singleSrcBuffer[0] = src;
1705         return singleSrcBuffer;
1706     }
1707 
resetSingleSrcBuffer()1708     private void resetSingleSrcBuffer() {
1709         singleSrcBuffer[0] = null;
1710     }
1711 
singleDstBuffer(ByteBuffer src)1712     private ByteBuffer[] singleDstBuffer(ByteBuffer src) {
1713         singleDstBuffer[0] = src;
1714         return singleDstBuffer;
1715     }
1716 
resetSingleDstBuffer()1717     private void resetSingleDstBuffer() {
1718         singleDstBuffer[0] = null;
1719     }
1720 
clientSessionContext()1721     private ClientSessionContext clientSessionContext() {
1722         return sslParameters.getClientSessionContext();
1723     }
1724 
sessionContext()1725     private AbstractSessionContext sessionContext() {
1726         return sslParameters.getSessionContext();
1727     }
1728 }
1729