下面列出了javax.net.ssl.SSLEngine#beginHandshake ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Test
public void testBeginHandshakeAfterEngineClosed() throws SSLException {
clientSslCtx = SslContextBuilder
.forClient()
.sslProvider(sslClientProvider())
.build();
SSLEngine client = clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT);
try {
client.closeInbound();
client.closeOutbound();
try {
client.beginHandshake();
fail();
} catch (SSLException expected) {
// expected
}
} finally {
cleanupClientSslEngine(client);
}
}
private void testBeginHandshakeCloseOutbound(SSLEngine engine) throws SSLException {
ByteBuffer dst = allocateBuffer(engine.getSession().getPacketBufferSize());
ByteBuffer empty = allocateBuffer(0);
engine.beginHandshake();
engine.closeOutbound();
SSLEngineResult result;
for (;;) {
result = engine.wrap(empty, dst);
dst.flip();
assertEquals(0, result.bytesConsumed());
assertEquals(dst.remaining(), result.bytesProduced());
if (result.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NEED_WRAP) {
break;
}
dst.clear();
}
assertEquals(SSLEngineResult.Status.CLOSED, result.getStatus());
}
protected SSLEngine newSslEngine(SocketChannel channel) throws IOException
{
SSLEngine sslEngine;
if (channel != null)
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
int peerPort = channel.socket().getPort();
sslEngine = _sslContextFactory.newSslEngine(peerHost, peerPort);
}
else
{
sslEngine = _sslContextFactory.newSslEngine();
}
sslEngine.setUseClientMode(true);
sslEngine.beginHandshake();
return sslEngine;
}
protected SSLEngine newSslEngine(SocketChannel channel) throws IOException
{
SSLEngine sslEngine;
if (channel != null)
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
int peerPort = channel.socket().getPort();
sslEngine = _sslContextFactory.newSslEngine(peerHost, peerPort);
}
else
{
sslEngine = _sslContextFactory.newSslEngine();
}
sslEngine.setUseClientMode(true);
sslEngine.beginHandshake();
return sslEngine;
}
protected SSLEngine newSslEngine(SocketChannel channel) throws IOException
{
SSLEngine sslEngine;
if (channel != null)
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
int peerPort = channel.socket().getPort();
sslEngine = _sslContextFactory.newSslEngine(peerHost, peerPort);
}
else
{
sslEngine = _sslContextFactory.newSslEngine();
}
sslEngine.setUseClientMode(true);
sslEngine.beginHandshake();
return sslEngine;
}
private static void testCloseInboundAfterBeginHandshake(SSLEngine engine) throws SSLException {
engine.beginHandshake();
try {
engine.closeInbound();
fail();
} catch (SSLException expected) {
// expected
}
}
void handshake(SSLEngine engine, ByteBuffer input, CodecCallback callback)
throws IOException {
if (!mHandshakeStarted) {
engine.beginHandshake();
mHandshakeStarted = true;
}
SSLEngineResult.HandshakeStatus status = engine.getHandshakeStatus();
while (!mHandshakeFinished) {
if (mEngineClosed) {
throw new IOException("Handshake failed: Engine is closed.");
}
if (status == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
// Should never happen
throw new IOException("Handshake failed: Invalid handshake status: " + status);
} else if (status == SSLEngineResult.HandshakeStatus.FINISHED) {
mHandshakeFinished = true;
NetBareLog.i("SSL handshake finished!");
if (input.hasRemaining()) {
decode(engine, input, callback);
}
} else if (status == SSLEngineResult.HandshakeStatus.NEED_WRAP) {
status = handshakeWrap(engine, callback).getHandshakeStatus();
} else if (status == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
// Wait next encrypted buffer.
if (!input.hasRemaining()) {
break;
}
status = handshakeUnwrap(engine, input, callback).getHandshakeStatus();
} else if (status == SSLEngineResult.HandshakeStatus.NEED_TASK) {
runDelegatedTasks(engine);
}
}
}
void startHandshaking(SSLEngine sslEngine) throws SSLException
{
handshaking = true;
sslEngine.beginHandshake();
myAppData.clear();
myNetData.clear();
peerAppData.clear();
peerNetData.clear();
peer.setOpInterest(SelectionKey.OP_WRITE);
}
HandshakeModel createSSLEngine(AsynchronousSocketChannel socketChannel, BufferPage bufferPage) {
try {
HandshakeModel handshakeModel = new HandshakeModel();
SSLEngine sslEngine = sslContext.createSSLEngine();
SSLSession session = sslEngine.getSession();
sslEngine.setUseClientMode(isClient);
if (clientAuth != null) {
switch (clientAuth) {
case OPTIONAL:
sslEngine.setWantClientAuth(true);
break;
case REQUIRE:
sslEngine.setNeedClientAuth(true);
break;
case NONE:
break;
default:
throw new Error("Unknown auth " + clientAuth);
}
}
handshakeModel.setSslEngine(sslEngine);
handshakeModel.setAppWriteBuffer(bufferPage.allocate(session.getApplicationBufferSize()));
handshakeModel.setNetWriteBuffer(bufferPage.allocate(session.getPacketBufferSize()));
handshakeModel.getNetWriteBuffer().buffer().flip();
handshakeModel.setAppReadBuffer(bufferPage.allocate(session.getApplicationBufferSize()));
handshakeModel.setNetReadBuffer(bufferPage.allocate(session.getPacketBufferSize()));
sslEngine.beginHandshake();
handshakeModel.setSocketChannel(socketChannel);
return handshakeModel;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected void handshake(SSLEngine clientEngine, SSLEngine serverEngine) throws SSLException {
ByteBuffer cTOs = allocateBuffer(clientEngine.getSession().getPacketBufferSize());
ByteBuffer sTOc = allocateBuffer(serverEngine.getSession().getPacketBufferSize());
ByteBuffer serverAppReadBuffer = allocateBuffer(
serverEngine.getSession().getApplicationBufferSize());
ByteBuffer clientAppReadBuffer = allocateBuffer(
clientEngine.getSession().getApplicationBufferSize());
clientEngine.beginHandshake();
serverEngine.beginHandshake();
ByteBuffer empty = allocateBuffer(0);
SSLEngineResult clientResult;
SSLEngineResult serverResult;
boolean clientHandshakeFinished = false;
boolean serverHandshakeFinished = false;
do {
int cTOsPos = cTOs.position();
int sTOcPos = sTOc.position();
if (!clientHandshakeFinished) {
clientResult = clientEngine.wrap(empty, cTOs);
runDelegatedTasks(clientResult, clientEngine);
assertEquals(empty.remaining(), clientResult.bytesConsumed());
assertEquals(cTOs.position() - cTOsPos, clientResult.bytesProduced());
if (isHandshakeFinished(clientResult)) {
clientHandshakeFinished = true;
}
}
if (!serverHandshakeFinished) {
serverResult = serverEngine.wrap(empty, sTOc);
runDelegatedTasks(serverResult, serverEngine);
assertEquals(empty.remaining(), serverResult.bytesConsumed());
assertEquals(sTOc.position() - sTOcPos, serverResult.bytesProduced());
if (isHandshakeFinished(serverResult)) {
serverHandshakeFinished = true;
}
}
cTOs.flip();
sTOc.flip();
cTOsPos = cTOs.position();
sTOcPos = sTOc.position();
if (!clientHandshakeFinished) {
int clientAppReadBufferPos = clientAppReadBuffer.position();
clientResult = clientEngine.unwrap(sTOc, clientAppReadBuffer);
runDelegatedTasks(clientResult, clientEngine);
assertEquals(sTOc.position() - sTOcPos, clientResult.bytesConsumed());
assertEquals(clientAppReadBuffer.position() - clientAppReadBufferPos, clientResult.bytesProduced());
if (isHandshakeFinished(clientResult)) {
clientHandshakeFinished = true;
}
} else {
assertFalse(sTOc.hasRemaining());
}
if (!serverHandshakeFinished) {
int serverAppReadBufferPos = serverAppReadBuffer.position();
serverResult = serverEngine.unwrap(cTOs, serverAppReadBuffer);
runDelegatedTasks(serverResult, serverEngine);
assertEquals(cTOs.position() - cTOsPos, serverResult.bytesConsumed());
assertEquals(serverAppReadBuffer.position() - serverAppReadBufferPos, serverResult.bytesProduced());
if (isHandshakeFinished(serverResult)) {
serverHandshakeFinished = true;
}
} else {
assertFalse(cTOs.hasRemaining());
}
sTOc.compact();
cTOs.compact();
} while (!clientHandshakeFinished || !serverHandshakeFinished);
}
private static SSLEngine newEngine() throws SSLException, NoSuchAlgorithmException {
SSLEngine engine = SSLContext.getDefault().createSSLEngine();
engine.setUseClientMode(true);
engine.beginHandshake();
return engine;
}
/**
* Perform the handshaking step of the TLS connection. We use the `sslEngine' along with the `channel' to exchange messages with the server to setup an
* encrypted channel.
*
* @param sslEngine
* {@link SSLEngine}
* @param channel
* {@link AsynchronousSocketChannel}
* @throws SSLException
* in case of handshake error
*/
private static void performTlsHandshake(SSLEngine sslEngine, AsynchronousSocketChannel channel) throws SSLException {
sslEngine.beginHandshake();
HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus();
// Create byte buffers to use for holding application data
int packetBufferSize = sslEngine.getSession().getPacketBufferSize();
ByteBuffer myNetData = ByteBuffer.allocate(packetBufferSize);
ByteBuffer peerNetData = ByteBuffer.allocate(packetBufferSize);
int appBufferSize = sslEngine.getSession().getApplicationBufferSize();
ByteBuffer myAppData = ByteBuffer.allocate(appBufferSize);
ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize);
SSLEngineResult res = null;
while (handshakeStatus != HandshakeStatus.FINISHED && handshakeStatus != HandshakeStatus.NOT_HANDSHAKING) {
switch (handshakeStatus) {
case NEED_WRAP:
myNetData.clear();
res = sslEngine.wrap(myAppData, myNetData);
handshakeStatus = res.getHandshakeStatus();
switch (res.getStatus()) {
case OK:
myNetData.flip();
write(channel, myNetData);
break;
case BUFFER_OVERFLOW:
case BUFFER_UNDERFLOW:
case CLOSED:
throw new CJCommunicationsException("Unacceptable SSLEngine result: " + res);
}
break;
case NEED_UNWRAP:
peerNetData.flip(); // Process incoming handshaking data
res = sslEngine.unwrap(peerNetData, peerAppData);
handshakeStatus = res.getHandshakeStatus();
switch (res.getStatus()) {
case OK:
peerNetData.compact();
break;
case BUFFER_OVERFLOW:
// Check if we need to enlarge the peer application data buffer.
final int newPeerAppDataSize = sslEngine.getSession().getApplicationBufferSize();
if (newPeerAppDataSize > peerAppData.capacity()) {
// enlarge the peer application data buffer
ByteBuffer newPeerAppData = ByteBuffer.allocate(newPeerAppDataSize);
newPeerAppData.put(peerAppData);
newPeerAppData.flip();
peerAppData = newPeerAppData;
} else {
peerAppData.compact();
}
break;
case BUFFER_UNDERFLOW:
// Check if we need to enlarge the peer network packet buffer
final int newPeerNetDataSize = sslEngine.getSession().getPacketBufferSize();
if (newPeerNetDataSize > peerNetData.capacity()) {
// enlarge the peer network packet buffer
ByteBuffer newPeerNetData = ByteBuffer.allocate(newPeerNetDataSize);
newPeerNetData.put(peerNetData);
newPeerNetData.flip();
peerNetData = newPeerNetData;
} else {
peerNetData.compact();
}
// obtain more inbound network data and then retry the operation
if (read(channel, peerNetData) < 0) {
throw new CJCommunicationsException("Server does not provide enough data to proceed with SSL handshake.");
}
break;
case CLOSED:
throw new CJCommunicationsException("Unacceptable SSLEngine result: " + res);
}
break;
case NEED_TASK:
sslEngine.getDelegatedTask().run();
handshakeStatus = sslEngine.getHandshakeStatus();
break;
case FINISHED:
case NOT_HANDSHAKING:
break;
}
}
}
/**
* Does the handshake of the two specified engines according to the
* {@code mode} specified.
*
* @param clientEngine - Client SSLEngine.
* @param serverEngine - Server SSLEngine.
* @param maxPacketSize - Maximum packet size for MFLN of zero
* for no limit.
* @param mode - Handshake mode according to
* {@link HandshakeMode} enum.
* @param enableReplicatedPacks - Set {@code true} to enable replicated
* packet sending.
* @throws SSLException - thrown on engine errors.
*/
public static void doHandshake(SSLEngine clientEngine,
SSLEngine serverEngine, int maxPacketSize,
HandshakeMode mode,
boolean enableReplicatedPacks) throws SSLException {
System.out.println("=============================================");
System.out.println("Starting handshake " + mode.name());
int loop = 0;
if (maxPacketSize < 0) {
throw new Error("Test issue: maxPacketSize is less than zero!");
}
SSLParameters params = clientEngine.getSSLParameters();
params.setMaximumPacketSize(maxPacketSize);
clientEngine.setSSLParameters(params);
params = serverEngine.getSSLParameters();
params.setMaximumPacketSize(maxPacketSize);
serverEngine.setSSLParameters(params);
SSLEngine firstEngine;
SSLEngine secondEngine;
switch (mode) {
case INITIAL_HANDSHAKE:
firstEngine = clientEngine;
secondEngine = serverEngine;
doUnwrapForNotHandshakingStatus = false;
clientEngine.beginHandshake();
serverEngine.beginHandshake();
break;
case REHANDSHAKE_BEGIN_CLIENT:
firstEngine = clientEngine;
secondEngine = serverEngine;
doUnwrapForNotHandshakingStatus = true;
clientEngine.beginHandshake();
break;
case REHANDSHAKE_BEGIN_SERVER:
firstEngine = serverEngine;
secondEngine = clientEngine;
doUnwrapForNotHandshakingStatus = true;
serverEngine.beginHandshake();
break;
default:
throw new Error("Test issue: unknown handshake mode");
}
endHandshakeLoop = false;
while (!endHandshakeLoop) {
if (++loop > MAX_HANDSHAKE_LOOPS) {
throw new Error("Too much loops for handshaking");
}
System.out.println("============================================");
System.out.println("Handshake loop " + loop + ": round 1");
System.out.println("==========================");
handshakeProcess(firstEngine, secondEngine, maxPacketSize,
enableReplicatedPacks);
if (endHandshakeLoop) {
break;
}
System.out.println("Handshake loop " + loop + ": round 2");
System.out.println("==========================");
handshakeProcess(secondEngine, firstEngine, maxPacketSize,
enableReplicatedPacks);
}
}
/**
* Perform the handshaking step of the TLS connection. We use the `sslEngine' along with the `channel' to exchange messages with the server to setup an
* encrypted channel.
*
* @param sslEngine
* {@link SSLEngine}
* @param channel
* {@link AsynchronousSocketChannel}
* @throws SSLException
* in case of handshake error
*/
private static void performTlsHandshake(SSLEngine sslEngine, AsynchronousSocketChannel channel) throws SSLException {
sslEngine.beginHandshake();
HandshakeStatus handshakeStatus = sslEngine.getHandshakeStatus();
// Create byte buffers to use for holding application data
int packetBufferSize = sslEngine.getSession().getPacketBufferSize();
ByteBuffer myNetData = ByteBuffer.allocate(packetBufferSize);
ByteBuffer peerNetData = ByteBuffer.allocate(packetBufferSize);
int appBufferSize = sslEngine.getSession().getApplicationBufferSize();
ByteBuffer myAppData = ByteBuffer.allocate(appBufferSize);
ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize);
SSLEngineResult res = null;
while (handshakeStatus != HandshakeStatus.FINISHED && handshakeStatus != HandshakeStatus.NOT_HANDSHAKING) {
switch (handshakeStatus) {
case NEED_WRAP:
myNetData.clear();
res = sslEngine.wrap(myAppData, myNetData);
handshakeStatus = res.getHandshakeStatus();
switch (res.getStatus()) {
case OK:
myNetData.flip();
write(channel, myNetData);
break;
case BUFFER_OVERFLOW:
case BUFFER_UNDERFLOW:
case CLOSED:
throw new CJCommunicationsException("Unacceptable SSLEngine result: " + res);
}
break;
case NEED_UNWRAP:
peerNetData.flip(); // Process incoming handshaking data
res = sslEngine.unwrap(peerNetData, peerAppData);
handshakeStatus = res.getHandshakeStatus();
switch (res.getStatus()) {
case OK:
peerNetData.compact();
break;
case BUFFER_OVERFLOW:
// Check if we need to enlarge the peer application data buffer.
final int newPeerAppDataSize = sslEngine.getSession().getApplicationBufferSize();
if (newPeerAppDataSize > peerAppData.capacity()) {
// enlarge the peer application data buffer
ByteBuffer newPeerAppData = ByteBuffer.allocate(newPeerAppDataSize);
newPeerAppData.put(peerAppData);
newPeerAppData.flip();
peerAppData = newPeerAppData;
} else {
peerAppData.compact();
}
break;
case BUFFER_UNDERFLOW:
// Check if we need to enlarge the peer network packet buffer
final int newPeerNetDataSize = sslEngine.getSession().getPacketBufferSize();
if (newPeerNetDataSize > peerNetData.capacity()) {
// enlarge the peer network packet buffer
ByteBuffer newPeerNetData = ByteBuffer.allocate(newPeerNetDataSize);
newPeerNetData.put(peerNetData);
newPeerNetData.flip();
peerNetData = newPeerNetData;
} else {
peerNetData.compact();
}
// obtain more inbound network data and then retry the operation
if (read(channel, peerNetData) < 0) {
throw new CJCommunicationsException("Server does not provide enough data to proceed with SSL handshake.");
}
break;
case CLOSED:
throw new CJCommunicationsException("Unacceptable SSLEngine result: " + res);
}
break;
case NEED_TASK:
sslEngine.getDelegatedTask().run();
handshakeStatus = sslEngine.getHandshakeStatus();
break;
case FINISHED:
case NOT_HANDSHAKING:
break;
}
}
}