Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Optimized JSSEngine #591

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmake/JSSConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,10 @@ macro(jss_config_template)
"${PROJECT_SOURCE_DIR}/tools/run_test.sh.in"
"${CMAKE_BINARY_DIR}/run_test.sh"
)
configure_file(
"${PROJECT_SOURCE_DIR}/tools/run_java.sh.in"
"${CMAKE_BINARY_DIR}/run_java.sh"
)
set(JSS_CFG_PATH "${CONFIG_OUTPUT_DIR}/jss.cfg")
configure_file(
"${PROJECT_SOURCE_DIR}/tools/java.security.in"
Expand Down
9 changes: 9 additions & 0 deletions cmake/JSSTests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ macro(jss_tests)
NAME "TestBufferPRFD"
COMMAND "${BIN_OUTPUT_DIR}/TestBufferPRFD"
)
jss_test_java(
NAME "TestJByteBuffer"
COMMAND "org.mozilla.jss.tests.TestJByteBuffer"
)
jss_test_java(
NAME "Test_UTF-8_Converter"
COMMAND "org.mozilla.jss.tests.UTF8ConverterTest"
Expand Down Expand Up @@ -175,6 +179,11 @@ macro(jss_tests)
COMMAND "pk12util" "-o" "${RESULTS_NSSDB_OUTPUT_DIR}/rsa.pfx" "-n" "CA_RSA" "-d" "${RESULTS_NSSDB_OUTPUT_DIR}" "-K" "${DB_PWD}" "-W" "${DB_PWD}"
DEPENDS "Generate_known_RSA_cert_pair"
)
jss_test_exec(
NAME "Create_PKCS11_cert_to_PKCS12_server_rsa.pfx"
COMMAND "pk12util" "-o" "${RESULTS_NSSDB_OUTPUT_DIR}/rsa-server.pfx" "-n" "Server_RSA" "-d" "${RESULTS_NSSDB_OUTPUT_DIR}" "-K" "${DB_PWD}" "-W" "${DB_PWD}"
DEPENDS "Generate_known_RSA_cert_pair"
)
jss_test_exec(
NAME "Create_PKCS11_cert_to_PKCS12_ecdsa.pfx"
COMMAND "pk12util" "-o" "${RESULTS_NSSDB_OUTPUT_DIR}/ecdsa.pfx" "-n" "CA_ECDSA" "-d" "${RESULTS_NSSDB_OUTPUT_DIR}" "-K" "${DB_PWD}" "-W" "${DB_PWD}"
Expand Down
5 changes: 4 additions & 1 deletion docs/usage/benchmarksslsocket.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ java.security. When utilizing SunJSSE, for best results, do not load
JSS via java.security.

It is suggested to use `run_test.sh` from the `build/` directory for
executing this utility.
executing this utility. `run_java.sh` can be used when benchmarking
`SunJSSE.SSLSocket` as it doesn't load JSS via the `java.security`
file by default. Additionally, a RSA server certificate is placed
under `build/results/nssdb/rsa-ssl.pfx` with the default password.

# Past Performance

Expand Down
8 changes: 8 additions & 0 deletions lib/jss.map
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,14 @@ Java_org_mozilla_jss_nss_SECErrors_getRevokedCertificateOCSP;
Java_org_mozilla_jss_nss_SECErrors_getRevokedCertificate;
Java_org_mozilla_jss_nss_SECErrors_getUntrustedIssuer;
Java_org_mozilla_jss_nss_SECErrors_getUntrustedCert;
Java_org_mozilla_jss_nss_Buffer_ReadOffset;
Java_org_mozilla_jss_nss_Buffer_WriteOffset;
Java_org_mozilla_jss_nss_JByteBuffer_Create;
Java_org_mozilla_jss_nss_JByteBuffer_ClearBufferNative;
Java_org_mozilla_jss_nss_JByteBuffer_SetBufferNative;
Java_org_mozilla_jss_nss_JByteBuffer_Capacity;
Java_org_mozilla_jss_nss_JByteBuffer_FreeNative;
Java_org_mozilla_jss_nss_PR_NewByteBufferPRFD;
local:
*;
};
Expand Down
51 changes: 51 additions & 0 deletions src/main/java/org/mozilla/jss/nss/ByteBufferProxy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <nspr.h>
#include <jni.h>

#include "java_ids.h"
#include "jssutil.h"
#include "ByteBufferProxy.h"

jobject
JSS_PR_wrapJByteBuffer(JNIEnv *env, j_bytebuffer **buffer)
{
jbyteArray pointer = NULL;
jclass proxyClass;
jmethodID constructor;
jobject bufferObj = NULL;

PR_ASSERT(env != NULL && buffer != NULL && *buffer != NULL);

/* convert pointer to byte array */
pointer = JSS_ptrToByteArray(env, *buffer);

/*
* Lookup the class and constructor
*/
proxyClass = (*env)->FindClass(env, BYTE_BUFFER_PROXY_CLASS_NAME);
if (proxyClass == NULL) {
ASSERT_OUTOFMEM(env);
goto finish;
}
constructor = (*env)->GetMethodID(env, proxyClass,
PLAIN_CONSTRUCTOR,
BYTE_BUFFER_PROXY_CONSTRUCTOR_SIG);
if (constructor == NULL) {
ASSERT_OUTOFMEM(env);
goto finish;
}

/* call the constructor */
bufferObj = (*env)->NewObject(env, proxyClass, constructor, pointer);

finish:
*buffer = NULL;

PR_ASSERT(bufferObj || (*env)->ExceptionOccurred(env));
return bufferObj;
}

PRStatus
JSS_PR_unwrapJByteBuffer(JNIEnv *env, jobject buffer_proxy, j_bytebuffer **buffer)
{
return JSS_getPtrFromProxy(env, buffer_proxy, (void**)buffer);
}
10 changes: 10 additions & 0 deletions src/main/java/org/mozilla/jss/nss/ByteBufferProxy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <jni.h>
#include "j_bytebuffer.h"

#pragma once

/* Wrap a j_buffer object into a BufferProxy, freeing the buffer on error. */
jobject JSS_PR_wrapJByteBuffer(JNIEnv *env, j_bytebuffer **buffer);

/* Extract a j_buffer pointer from an instance of a BufferProxy. */
PRStatus JSS_PR_unwrapJByteBuffer(JNIEnv *env, jobject buffer_proxy, j_bytebuffer **buffer);
25 changes: 25 additions & 0 deletions src/main/java/org/mozilla/jss/nss/ByteBufferProxy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.mozilla.jss.nss;

import java.nio.ByteBuffer;

public class ByteBufferProxy extends org.mozilla.jss.util.NativeProxy {
protected ByteBuffer last;

public ByteBufferProxy(byte[] pointer) {
super(pointer);
}

/**
* It is usually better to call org.mozilla.jss.nss.JByteBuffer.Free(...)
* instead.
*
* But this does it for you.
*/
protected void releaseNativeResources() {
JByteBuffer.Free(this);
}

protected void finalize() throws Throwable {
super.finalize();
}
}
89 changes: 89 additions & 0 deletions src/main/java/org/mozilla/jss/nss/JByteBuffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include <nspr.h>
#include <limits.h>
#include <stdint.h>
#include <jni.h>

#include "jssutil.h"
#include "ByteBufferProxy.h"
#include "j_bytebuffer.h"

#include "_jni/org_mozilla_jss_nss_JByteBuffer.h"

JNIEXPORT jobject JNICALL
Java_org_mozilla_jss_nss_JByteBuffer_Create(JNIEnv *env, jclass clazz,
jboolean writable)
{
j_bytebuffer *buf = NULL;

PR_ASSERT(env != NULL);

buf = jbb_alloc(writable == JNI_TRUE);

PR_ASSERT(buf != NULL);

return JSS_PR_wrapJByteBuffer(env, &buf);
}

JNIEXPORT jint JNICALL
Java_org_mozilla_jss_nss_JByteBuffer_ClearBufferNative(JNIEnv *env,
jclass clazz, jobject proxy, jbyteArray last)
{
j_bytebuffer *buf = NULL;

PR_ASSERT(env != NULL && proxy != NULL);

if (JSS_PR_unwrapJByteBuffer(env, proxy, &buf) != PR_SUCCESS) {
return 0;
}

return jbb_clear_buffer(buf, env, last);
}

JNIEXPORT jboolean JNICALL
Java_org_mozilla_jss_nss_JByteBuffer_SetBufferNative(JNIEnv *env,
jclass clazz, jobject proxy, jbyteArray array, jlong offset,
jlong limit)
{
j_bytebuffer *buf = NULL;

PR_ASSERT(env != NULL && proxy != NULL);

if (JSS_PR_unwrapJByteBuffer(env, proxy, &buf) != PR_SUCCESS ||
buf == NULL) {
return JNI_FALSE;
}

return jbb_set_buffer(buf, env, array, offset, limit);
}

JNIEXPORT jint JNICALL
Java_org_mozilla_jss_nss_JByteBuffer_Capacity(JNIEnv *env,
jclass clazz, jobject proxy)
{
j_bytebuffer *buf = NULL;

PR_ASSERT(env != NULL && proxy != NULL);

if (JSS_PR_unwrapJByteBuffer(env, proxy, &buf) != PR_SUCCESS) {
return 0;
}

return jbb_capacity(buf);
}

JNIEXPORT void JNICALL
Java_org_mozilla_jss_nss_JByteBuffer_FreeNative(JNIEnv *env, jclass clazz,
jobject proxy)
{
j_bytebuffer *buf = NULL;

PR_ASSERT(env != NULL && proxy != NULL);

if (JSS_PR_unwrapJByteBuffer(env, proxy, &buf) != PR_SUCCESS ||
buf == NULL) {
return;
}

jbb_free(buf, env);
JSS_clearPtrFromProxy(env, proxy);
}
97 changes: 97 additions & 0 deletions src/main/java/org/mozilla/jss/nss/JByteBuffer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package org.mozilla.jss.nss;

import java.nio.ByteBuffer;

public class JByteBuffer {
/**
* Create a new j_buffer object with the specified number of bytes.
*
* See also: jbb_alloc in org/mozilla/jss/ssl/javax/j_bytebuffer.h
*/
public static native ByteBufferProxy Create(boolean writable);

/**
* Removes the existing ByteBuffer from this proxy instance.
*
* See also: jbb_clear_buffer in org/mozilla/jss/ssl/javax/j_bytebuffer.h
*/
public static int ClearBuffer(ByteBufferProxy proxy) {
if (proxy == null || proxy.last == null) {
return 0;
}

int offset = ClearBufferNative(proxy, proxy.last.array());
proxy.last.position(proxy.last.position() + offset);

proxy.last = null;

return offset;
}

/**
* Set the underlying buffer for this ByteBufferProxy instance.
*
* See also: jbb_set_buffer in org/mozilla/jss/ssl/javax/j_bytebuffer.h
*/
public static void SetBuffer(ByteBufferProxy proxy, ByteBuffer buffer) {
if (proxy == null) {
return;
}

if (buffer != null && !buffer.hasArray()) {
String msg = "Unable to support ByteBuffers which are not backed ";
msg += "by real arrays.";
throw new RuntimeException(msg);
}

if (proxy.last != null) {
// This is an unusual case. We should always clear the last buffer
// prior to attempting to set a new one. Luckily, we store the
// last buffer, so we can clean up safely.
ClearBuffer(proxy);
}

if (!SetBufferNative(proxy, buffer.array(), buffer.position(), buffer.limit())) {
throw new RuntimeException("Unable to set bufer for an unknown reason.");
}

proxy.last = buffer;
}

/**
* Get the remaining capacity of this buffer.
*
* See also: jbb_capacity in org/mozilla/jss/ssl/javax/j_bytebuffer.h
*/
public static native int Capacity(ByteBufferProxy proxy);

/**
* Clear the underlying buffer for this ByteBufferProxy instance.
*/
private static native int ClearBufferNative(ByteBufferProxy proxy, byte[] last);

/**
* Internal helper to implement the native portion of SetBuffer.
*
* See also: jbb_set_buffer in org/mozilla/jss/ssl/javax/j_bytebuffer.h
*/
private static native boolean SetBufferNative(ByteBufferProxy proxy, byte[] array, long offset, long limit);

/**
* Destroy a buffer object, freeing its resources.
*
* See also: jbb_free in org/mozilla/jss/ssl/javax/j_buffer.h
*/
public static void Free(ByteBufferProxy proxy) {
// Make sure we call ClearBuffer ourselves; otherwise, any changes to
// the underlying ByteBuffer won't be reflected as FreeNative will
// discard them.
ClearBuffer(proxy);
FreeNative(proxy);
}

/**
* Internal helper to implement the free call.
*/
private static native void FreeNative(ByteBufferProxy proxy);
}
Loading