@Override public final void setEnabledCipherSuites(String[] cipherSuites) { checkNotNull(cipherSuites, "cipherSuites"); final StringBuilder buf = new StringBuilder(); final StringBuilder bufTLSv13 = new StringBuilder(); CipherSuiteConverter.convertToCipherStrings(Arrays.asList(cipherSuites), buf, bufTLSv13, OpenSsl.isBoringSSL()); final String cipherSuiteSpec = buf.toString(); final String cipherSuiteSpecTLSv13 = bufTLSv13.toString(); if (!OpenSsl.isTlsv13Supported() && !cipherSuiteSpecTLSv13.isEmpty()) { throw new IllegalArgumentException("TLSv1.3 is not supported by this java version."); } synchronized (this) { if (!isDestroyed()) { // TODO: Should we also adjust the protocols based on if there are any ciphers left that can be used // for TLSv1.3 or for previor SSL/TLS versions ? try { // Set non TLSv1.3 ciphers. SSL.setCipherSuites(ssl, cipherSuiteSpec, false); if (OpenSsl.isTlsv13Supported()) { // Set TLSv1.3 ciphers. SSL.setCipherSuites(ssl, cipherSuiteSpecTLSv13, true); } } catch (Exception e) { throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec, e); } } else { throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec); } } }
void setKeyMaterialServerSide(ReferenceCountedOpenSslEngine engine) throws SSLException { long ssl = engine.sslPointer(); String[] authMethods = SSL.authenticationMethods(ssl); Set<String> aliases = new HashSet<String>(authMethods.length); for (String authMethod : authMethods) { String type = KEY_TYPES.get(authMethod); if (type != null) { String alias = chooseServerAlias(engine, type); if (alias != null && aliases.add(alias)) { setKeyMaterial(engine, alias); } } } }
SSL.bioSetByteBuffer(networkBIO, bufferAddress(dst) + dst.position(), dst.remaining(), true); } else { bioReadCopyBuf = alloc.directBuffer(dst.remaining()); SSL.bioSetByteBuffer(networkBIO, memoryAddress(bioReadCopyBuf), bioReadCopyBuf.writableBytes(), true); int bioLengthBefore = SSL.bioLengthByteBuffer(networkBIO); bytesProduced = SSL.bioFlushByteBuffer(networkBIO); if (bytesProduced <= 0) { return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, 0); bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO); return newResultMayFinishHandshake(NEED_WRAP, 0, bytesProduced); bytesProduced = SSL.bioFlushByteBuffer(networkBIO); bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO); getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED), 0, bytesProduced); bytesProduced = SSL.bioFlushByteBuffer(networkBIO); return newResultMayFinishHandshake(status, 0, bytesProduced); bytesProduced = SSL.bioFlushByteBuffer(networkBIO); for (; offset < endOffset; ++offset) { final ByteBuffer src = srcs[offset];
/** * Destroys this engine. */ public final synchronized void shutdown() { if (DESTROYED_UPDATER.compareAndSet(this, 0, 1)) { engineMap.remove(ssl); SSL.freeSSL(ssl); ssl = networkBIO = 0; isInboundDone = outboundClosed = true; } // On shutdown clear all errors SSL.clearError(); }
private static long newBIO(ByteBuf buffer) throws Exception { try { long bio = SSL.newMemBIO(); int readable = buffer.readableBytes(); if (SSL.bioWrite(bio, OpenSsl.memoryAddress(buffer) + buffer.readerIndex(), readable) != readable) { SSL.freeBIO(bio); throw new IllegalStateException("Could not write data to memory BIO"); } return bio; } finally { buffer.release(); } }
/** * Attempt to call {@link SSL#shutdownSSL(long)}. * @return {@code false} if the call to {@link SSL#shutdownSSL(long)} was not attempted or returned an error. */ private boolean doSSLShutdown() { if (SSL.isInInit(ssl) != 0) { // Only try to call SSL_shutdown if we are not in the init state anymore. // Otherwise we will see 'error:140E0197:SSL routines:SSL_shutdown:shutdown while in init' in our logs. // // See also http://hg.nginx.org/nginx/rev/062c189fee20 return false; } int err = SSL.shutdownSSL(ssl); if (err < 0) { int sslErr = SSL.getError(ssl, err); if (sslErr == SSL.SSL_ERROR_SYSCALL || sslErr == SSL.SSL_ERROR_SSL) { if (logger.isDebugEnabled()) { int error = SSL.getLastErrorNumber(); logger.debug("SSL_shutdown failed: OpenSSL error: {} {}", error, SSL.getErrorString(error)); } // There was an internal error -- shutdown shutdown(); return false; } SSL.clearError(); } return true; }
final long finalSsl; try { finalSsl = SSL.newSSL(context.ctx, !context.isClient()); } finally { readerLock.unlock(); ssl = finalSsl; try { networkBIO = SSL.bioNewByteBuffer(ssl, context.getBioNonApplicationBufferSize()); SSL.setTlsExtHostName(ssl, peerHost); sniHostNames = Collections.singletonList(peerHost); SSL.enableOcsp(ssl); SSL.setMode(ssl, SSL.getMode(ssl) | SSL.SSL_MODE_ENABLE_PARTIAL_WRITE); SSL.freeSSL(ssl); PlatformDependent.throwException(cause);
} else { bioWriteCopyBuf = null; pendingEncryptedBytes = SSL.bioLengthByteBuffer(networkBIO); int localBytesConsumed = pendingEncryptedBytes - SSL.bioLengthByteBuffer(networkBIO); bytesConsumed += localBytesConsumed; packetLength -= localBytesConsumed; int sslError = SSL.getError(ssl, bytesRead); if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) { bytesConsumed, bytesProduced); } else { return sslReadErrorResult(sslError, SSL.getLastErrorNumber(), bytesConsumed, bytesProduced); SSL.bioClearByteBuffer(networkBIO); rejectRemoteInitiatedRenegotiation(); if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) { closeAll();
/** * Attempt to call {@link SSL#shutdownSSL(long)}. * @return {@code false} if the call to {@link SSL#shutdownSSL(long)} was not attempted or returned an error. */ private boolean doSSLShutdown() { if (SSL.isInInit(ssl) != 0) { // Only try to call SSL_shutdown if we are not in the init state anymore. // Otherwise we will see 'error:140E0197:SSL routines:SSL_shutdown:shutdown while in init' in our logs. // // See also http://hg.nginx.org/nginx/rev/062c189fee20 return false; } int err = SSL.shutdownSSL(ssl); if (err < 0) { int sslErr = SSL.getError(ssl, err); if (sslErr == SSL.SSL_ERROR_SYSCALL || sslErr == SSL.SSL_ERROR_SSL) { if (logger.isDebugEnabled()) { logger.debug("SSL_shutdown failed: OpenSSL error: {}", SSL.getLastError()); } // There was an internal error -- shutdown shutdown(); return false; } SSL.clearError(); } return true; }
if (SSL.bioLengthNonApplication(networkBIO) > 0) { int code = SSL.doHandshake(ssl); if (code <= 0) { int sslError = SSL.getError(ssl, code); if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) { return pendingStatus(SSL.bioLengthNonApplication(networkBIO)); } else {
private SSLEngineResult sslReadErrorResult(int error, int stackError, int bytesConsumed, int bytesProduced) throws SSLException { // Check if we have a pending handshakeException and if so see if we need to consume all pending data from the // BIO first or can just shutdown and throw it now. // This is needed so we ensure close_notify etc is correctly send to the remote peer. // See https://github.com/netty/netty/issues/3900 if (SSL.bioLengthNonApplication(networkBIO) > 0) { if (handshakeException == null && handshakeState != HandshakeState.FINISHED) { // we seems to have data left that needs to be transferred and so the user needs // call wrap(...). Store the error so we can pick it up later. handshakeException = new SSLHandshakeException(SSL.getErrorString(stackError)); } // We need to clear all errors so we not pick up anything that was left on the stack on the next // operation. Note that shutdownWithError(...) will cleanup the stack as well so its only needed here. SSL.clearError(); return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced); } throw shutdownWithError("SSL_read", error, stackError); }
@Override public final synchronized boolean isOutboundDone() { // Check if there is anything left in the outbound buffer. // We need to ensure we only call SSL.pendingWrittenBytesInBIO(...) if the engine was not destroyed yet. return outboundClosed && (networkBIO == 0 || SSL.bioLengthNonApplication(networkBIO) == 0); }
private SSLEngineResult sslReadErrorResult(int err, int bytesConsumed, int bytesProduced) throws SSLException { String errStr = SSL.getErrorString(err); // Check if we have a pending handshakeException and if so see if we need to consume all pending data from the // BIO first or can just shutdown and throw it now. // This is needed so we ensure close_notify etc is correctly send to the remote peer. // See https://github.com/netty/netty/issues/3900 if (SSL.bioLengthNonApplication(networkBIO) > 0) { if (handshakeException == null && handshakeState != HandshakeState.FINISHED) { // we seems to have data left that needs to be transfered and so the user needs // call wrap(...). Store the error so we can pick it up later. handshakeException = new SSLHandshakeException(errStr); } return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced); } throw shutdownWithError("SSL_read", errStr); }
/** * Write encrypted data to the OpenSSL network BIO. */ private ByteBuf writeEncryptedData(final ByteBuffer src, int len) { final int pos = src.position(); if (src.isDirect()) { SSL.bioSetByteBuffer(networkBIO, bufferAddress(src) + pos, len, false); } else { final ByteBuf buf = alloc.directBuffer(len); try { final int limit = src.limit(); src.limit(pos + len); buf.writeBytes(src); // Restore the original position and limit because we don't want to consume from `src`. src.position(pos); src.limit(limit); SSL.bioSetByteBuffer(networkBIO, memoryAddress(buf), len, false); return buf; } catch (Throwable cause) { buf.release(); PlatformDependent.throwException(cause); } } return null; }
void setKeyMaterialServerSide(ReferenceCountedOpenSslEngine engine) throws SSLException { long ssl = engine.sslPointer(); String[] authMethods = SSL.authenticationMethods(ssl); Set<String> aliases = new HashSet<String>(authMethods.length); for (String authMethod : authMethods) { String type = KEY_TYPES.get(authMethod); if (type != null) { String alias = chooseServerAlias(engine, type); if (alias != null && aliases.add(alias)) { OpenSslKeyMaterial keyMaterial = null; try { keyMaterial = provider.chooseKeyMaterial(engine.alloc, alias); if (keyMaterial != null) { SSL.setKeyMaterialServerSide( ssl, keyMaterial.certificateChainAddress(), keyMaterial.privateKeyAddress()); } } catch (SSLException e) { throw e; } catch (Exception e) { throw new SSLException(e); } finally { if (keyMaterial != null) { keyMaterial.release(); } } } } } }
final long finalSsl; try { finalSsl = SSL.newSSL(context.ctx, !context.isClient()); } finally { readerLock.unlock(); ssl = finalSsl; try { networkBIO = SSL.bioNewByteBuffer(ssl, context.getBioNonApplicationBufferSize()); SSL.setTlsExtHostName(ssl, peerHost); sniHostNames = Collections.singletonList(peerHost); SSL.enableOcsp(ssl); SSL.setMode(ssl, SSL.getMode(ssl) | SSL.SSL_MODE_ENABLE_PARTIAL_WRITE);
} else { bioWriteCopyBuf = null; pendingEncryptedBytes = SSL.bioLengthByteBuffer(networkBIO); int localBytesConsumed = pendingEncryptedBytes - SSL.bioLengthByteBuffer(networkBIO); bytesConsumed += localBytesConsumed; packetLength -= localBytesConsumed; int sslError = SSL.getError(ssl, bytesRead); if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) { bytesConsumed, bytesProduced); } else { return sslReadErrorResult(SSL.getLastErrorNumber(), bytesConsumed, bytesProduced); SSL.bioClearByteBuffer(networkBIO); rejectRemoteInitiatedRenegotiation(); if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) { closeAll();
/** * Attempt to call {@link SSL#shutdownSSL(long)}. * @return {@code false} if the call to {@link SSL#shutdownSSL(long)} was not attempted or returned an error. */ private boolean doSSLShutdown() { if (SSL.isInInit(ssl) != 0) { // Only try to call SSL_shutdown if we are not in the init state anymore. // Otherwise we will see 'error:140E0197:SSL routines:SSL_shutdown:shutdown while in init' in our logs. // // See also http://hg.nginx.org/nginx/rev/062c189fee20 return false; } int err = SSL.shutdownSSL(ssl); if (err < 0) { int sslErr = SSL.getError(ssl, err); if (sslErr == SSL.SSL_ERROR_SYSCALL || sslErr == SSL.SSL_ERROR_SSL) { if (logger.isDebugEnabled()) { logger.debug("SSL_shutdown failed: OpenSSL error: {}", SSL.getLastError()); } // There was an internal error -- shutdown shutdown(); return false; } SSL.clearError(); } return true; }
/** * Attempt to call {@link SSL#shutdownSSL(long)}. * @return {@code false} if the call to {@link SSL#shutdownSSL(long)} was not attempted or returned an error. */ private boolean doSSLShutdown() { if (SSL.isInInit(ssl) != 0) { // Only try to call SSL_shutdown if we are not in the init state anymore. // Otherwise we will see 'error:140E0197:SSL routines:SSL_shutdown:shutdown while in init' in our logs. // // See also http://hg.nginx.org/nginx/rev/062c189fee20 return false; } int err = SSL.shutdownSSL(ssl); if (err < 0) { int sslErr = SSL.getError(ssl, err); if (sslErr == SSL.SSL_ERROR_SYSCALL || sslErr == SSL.SSL_ERROR_SSL) { if (logger.isDebugEnabled()) { int error = SSL.getLastErrorNumber(); logger.debug("SSL_shutdown failed: OpenSSL error: {} {}", error, SSL.getErrorString(error)); } // There was an internal error -- shutdown shutdown(); return false; } SSL.clearError(); } return true; }
private static long newBIO(ByteBuf buffer) throws Exception { try { long bio = SSL.newMemBIO(); int readable = buffer.readableBytes(); if (SSL.bioWrite(bio, OpenSsl.memoryAddress(buffer) + buffer.readerIndex(), readable) != readable) { SSL.freeBIO(bio); throw new IllegalStateException("Could not write data to memory BIO"); } return bio; } finally { buffer.release(); } }