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

Spake #1275

Closed
wants to merge 7 commits into from
Closed

Spake #1275

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
18 changes: 14 additions & 4 deletions android/src/main/java/org/conscrypt/Platform.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,21 @@
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.StandardConstants;
import javax.net.ssl.X509TrustManager;
import org.conscrypt.NativeCrypto;

/**
* Platform-specific methods for unbundled Android.
*/
@Internal
final public class Platform {
private static final String TAG = "Conscrypt";
static boolean DEPRECATED_TLS_V1 = true;
static boolean ENABLED_TLS_V1 = false;
private static boolean FILTERED_TLS_V1 = true;

private static Method m_getCurveName;
static {
NativeCrypto.setTlsV1DeprecationStatus(DEPRECATED_TLS_V1, ENABLED_TLS_V1);
try {
m_getCurveName = ECParameterSpec.class.getDeclaredMethod("getCurveName");
m_getCurveName.setAccessible(true);
Expand All @@ -89,7 +94,12 @@ final public class Platform {

private Platform() {}

public static void setup() {}
public static void setup(boolean deprecatedTlsV1, boolean enabledTlsV1) {
DEPRECATED_TLS_V1 = deprecatedTlsV1;
ENABLED_TLS_V1 = enabledTlsV1;
FILTERED_TLS_V1 = !enabledTlsV1;
NativeCrypto.setTlsV1DeprecationStatus(DEPRECATED_TLS_V1, ENABLED_TLS_V1);
}

/**
* Default name used in the {@link java.security.Security JCE system} by {@code OpenSSLProvider}
Expand Down Expand Up @@ -955,14 +965,14 @@ public static boolean isJavaxCertificateSupported() {
}

public static boolean isTlsV1Deprecated() {
return true;
return DEPRECATED_TLS_V1;
}

public static boolean isTlsV1Filtered() {
return false;
return FILTERED_TLS_V1;
}

public static boolean isTlsV1Supported() {
return false;
return ENABLED_TLS_V1;
}
}
264 changes: 264 additions & 0 deletions common/src/jni/main/cpp/conscrypt/native_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10891,6 +10891,270 @@ static jbyteArray NativeCrypto_Scrypt_generate_key(JNIEnv* env, jclass, jbyteArr
return key_bytes;
}


#define SPAKE2PLUS_PW_VERIFIER_SIZE 32
#define SPAKE2PLUS_REGISTRATION_RECORD_SIZE 65

static jobjectArray NativeCrypto_SPAKE2PLUS_register(
JNIEnv* env, jclass,
jbyteArray pwArray, jint pwLen, jbyteArray idProverArray,
jlong idProverLen, jbyteArray idVerifierArray, jlong idVerifierLen) {
CHECK_ERROR_QUEUE_ON_RETURN;
JNI_TRACE("SPAKE2PLUS_register(%p, %d, %p, %ld, %p, %ld)",
pwArray,
pwLen,
idProverArray,
idProverLen,
idVerifierArray,
idVerifierLen);

if (pwArray == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "pw == null");
return {};
}

if (idProverArray == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "idProver == null");
return {};
}

if (idVerifierArray == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "idVerifier == null");
return {};
}

ScopedByteArrayRO pw_bytes(env, pwArray);
if (pw_bytes.get() == nullptr) {
return {};
}

ScopedByteArrayRO id_prover_bytes(env, idProverArray);
if (id_prover_bytes.get() == nullptr) {
return {};
}

ScopedByteArrayRO id_verifier_bytes(env, idVerifierArray);
if (id_verifier_bytes.get() == nullptr) {
return {};
}

ScopedByteArrayRO peer_public_key(env, pwArray);

uint8_t pwVerifierW0[SPAKE2PLUS_PW_VERIFIER_SIZE];
uint8_t pwVerifierW1[SPAKE2PLUS_PW_VERIFIER_SIZE];
uint8_t registrationRecord[SPAKE2PLUS_REGISTRATION_RECORD_SIZE];

if (!SPAKE2PLUS_register(
/* out_pw_verifier_w0= */ pwVerifierW0,
/* out_pw_verifier_w1= */ pwVerifierW1,
/* out_registration_record= */ registrationRecord,
/* pw= */ pw_bytes,
/* pw_len= */ pwLen,
/* id_prover= */ id_prover_bytes,
/* id_prover_len= */ idProverLen,
/* id_verifier= */ id_verifier_bytes,
/* id_verifier_len= */ idVerifierLen)) {
conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SPAKE2PLUS_register");
return {};
}

ScopedLocalRef<jbyteArray> pwArray0(env, env->NewByteArray(static_cast<jsize>(SPAKE2PLUS_PW_VERIFIER_SIZE)));
if (pwArray0.get() == nullptr) {
return {};
}
ScopedByteArrayRW encBytes0(env, pwArray0.get());
if (encBytes0.get() == nullptr) {
return {};
}
memcpy(encBytes0.get(), reinterpret_cast<const jbyte*>(pwVerifierW0), SPAKE2PLUS_PW_VERIFIER_SIZE);

ScopedLocalRef<jbyteArray> pwArray1(env, env->NewByteArray(static_cast<jsize>(SPAKE2PLUS_PW_VERIFIER_SIZE)));
if (pwArray1.get() == nullptr) {
return {};
}
ScopedByteArrayRW encBytes1(env, pwArray1.get());
if (encBytes1.get() == nullptr) {
return {};
}
memcpy(encBytes1.get(), reinterpret_cast<const jbyte*>(pwVerifierW1), SPAKE2PLUS_PW_VERIFIER_SIZE);

ScopedLocalRef<jbyteArray> registrationRecordArray(env, env->NewByteArray(static_cast<jsize>(SPAKE2PLUS_REGISTRATION_RECORD_SIZE)));
if (registrationRecordArray.get() == nullptr) {
return {};
}
ScopedByteArrayRW registrationRecordBytes(env, registrationRecordArray.get());
if (registrationRecordBytes.get() == nullptr) {
return {};
}
memcpy(registrationRecordBytes.get(), reinterpret_cast<const jbyte*>(registrationRecord), SPAKE2PLUS_REGISTRATION_RECORD_SIZE);

ScopedLocalRef<jobjectArray> result(
env, env->NewObjectArray(3, conscrypt::jniutil::objectClass, nullptr));

env->SetObjectArrayElement(result.get(), 0, pwArray0.release());
env->SetObjectArrayElement(result.get(), 1, pwArray1.release());
env->SetObjectArrayElement(result.get(), 2, registrationRecordArray.release());

return result.release();
}

static jobject NativeCrypto_SSL_CREDENTIAL_new_SPAKE2PLUSV1(
JNIEnv* env, jclass) {
CHECK_ERROR_QUEUE_ON_RETURN;
JNI_TRACE("SSL_CREDENTIAL_new_SPAKE2PLUSV1");
SSL_CREDENTIAL* creds = SSL_CREDENTIAL_new_SPAKE2PLUSV1();
if (creds == nullptr) {
conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CREDENTIAL_new_SPAKE2PLUSV1 failed");
return nullptr;
}
return reinterpret_cast<jobject>(creds);

}

static void NativeCrypto_SSL_CREDENTIAL_set1_PAKE_identities(
JNIEnv* env, jclass, jobject sslCredential, jbyteArray context,
jlong contextLen, jbyteArray serverIdentityArray, jlong serverIdentityLen,
jbyteArray clientIdentityArray, jlong clientIdentityLen) {
CHECK_ERROR_QUEUE_ON_RETURN;
JNI_TRACE("SSL_CREDENTIAL_set1_PAKE_identities(%p, %p, %jd, %jd, %p, %jd, %p, %jd)",
sslCredential, context, contextLen, serverIdentityArray, serverIdentityLen,
clientIdentityArray, clientIdentityLen);

SSL_CREDENTIAL* creds = reinterpret_cast<SSL_CREDENTIAL*>(sslCredential);
if (creds == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "sslCredential cannot be null");
return;
}
if (context == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "context cannot be null");
return;
}
if (serverIdentityArray == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "serverIdentityArray cannot be null");
return;
}
if (clientIdentityArray == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "clientIdentityArray cannot be null");
return;
}

ScopedByteArrayRO context_bytes(env, context);
if (context_bytes.get() == nullptr) {
return;
}

ScopedByteArrayRO server_identity_bytes(env, serverIdentityArray);
if (server_identity_bytes.get() == nullptr) {
return;
}

ScopedByteArrayRO client_identity_bytes(env, clientIdentityArray);
if (client_identity_bytes.get() == nullptr) {
return;
}

int ret = SSL_CREDENTIAL_set1_PAKE_identities(
creds, reinterpret_cast<const uint8_t*>(context_bytes.get()), contextLen,
reinterpret_cast<const uint8_t*>(client_identity_bytes.get()),
clientIdentityLen,
reinterpret_cast<const uint8_t*>(server_identity_bytes.get()),
serverIdentityLen);

if (ret != 1) {
conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CREDENTIAL_set1_PAKE_identities failed");
}
}

static void NativeCrypto_SSL_CREDENTIAL_set1_PAKE_client_password_record(
JNIEnv* env, jclass,
jobject sslCredential, jbyteArray password, jlong passwordLen
) {
CHECK_ERROR_QUEUE_ON_RETURN;
JNI_TRACE("SSL_CREDENTIAL_set1_PAKE_client_password_record(%p, %p, %ld)",
sslCredential, password, passwordLen);
SSL_CREDENTIAL* creds = reinterpret_cast<SSL_CREDENTIAL*>(sslCredential);
if (creds == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "sslCredential cannot be null");
return;
}
if (password == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "password cannot be null");
return;
}

ScopedByteArrayRO password_bytes(env, password);
if (password_bytes.get() == nullptr) {
return;
}

int ret = SSL_CREDENTIAL_set1_PAKE_client_password_record(
creds, reinterpret_cast<const uint8_t*>(password_bytes.get()), passwordLen);
if (ret != 1) {
conscrypt::jniutil::throwNullPointerException(
env, "SSL_CREDENTIAL_set1_PAKE_client_password_record failed");
}
}

static void NativeCrypto_SSL_CREDENTIAL_set1_PAKE_server_password_record(
JNIEnv* env, jclass, jobject sslCredential,
jbyteArray password, jlong passwordLen, jbyteArray registration, jlong registrationLen
) {
CHECK_ERROR_QUEUE_ON_RETURN;
JNI_TRACE("SSL_CREDENTIAL_set1_PAKE_server_password_record(%p, %p, %ld, %p, %ld)",
sslCredential, password, passwordLen, registration, registrationLen);
SSL_CREDENTIAL* creds = reinterpret_cast<SSL_CREDENTIAL*>(sslCredential);
if (creds == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "sslCredential cannot be null");
return;
}
if (password == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "password cannot be null");
return;
}
if (registration == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "registration cannot be null");
return;
}

ScopedByteArrayRO password_bytes(env, password);
if (password_bytes.get() == nullptr) {
return;
}

ScopedByteArrayRO registration_bytes(env, registration);
if (registration_bytes.get() == nullptr) {
return;
}

int ret = SSL_CREDENTIAL_set1_PAKE_server_password_record(
creds, reinterpret_cast<const uint8_t*>(password_bytes.get()), passwordLen,
reinterpret_cast<const uint8_t*>(registration_bytes.get()),
registrationLen);
if (ret != 1) {
conscrypt::jniutil::throwNullPointerException(
env, "SSL_CREDENTIAL_set1_PAKE_server_password_record failed");
}
}


static void NativeCrypto_SSL_CTX_add1_credential(
JNIEnv* env, jclass, jobject sslCtx, jlong sslCredential) {
CHECK_ERROR_QUEUE_ON_RETURN;
JNI_TRACE("SSL_CTX_add1_credential(%p, %p)", sslCtx, sslCredential);
SSL_CTX* ctx = reinterpret_cast<SSL_CTX*>(sslCtx);
if (ctx == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "sslCtx cannot be null");
}
SSL_CREDENTIAL* creds = reinterpret_cast<SSL_CREDENTIAL*>(sslCredential);
if (creds == nullptr) {
conscrypt::jniutil::throwNullPointerException(env, "sslCredential cannot be null");
}
int ret = SSL_CTX_add1_credential(ctx, creds);
if (ret != 1) {
conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "SSL_CTX_add1_credential failed");
}
}

// TESTING METHODS BEGIN

static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
Expand Down
17 changes: 16 additions & 1 deletion common/src/main/java/org/conscrypt/Conscrypt.java
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ public static class ProviderBuilder {
private String name = Platform.getDefaultProviderName();
private boolean provideTrustManager = Platform.provideTrustManagerByDefault();
private String defaultTlsProtocol = NativeCrypto.SUPPORTED_PROTOCOL_TLSV1_3;
private boolean deprecatedTlsV1 = true;
private boolean enabledTlsV1 = false;

private ProviderBuilder() {}

Expand Down Expand Up @@ -200,8 +202,21 @@ public ProviderBuilder defaultTlsProtocol(String defaultTlsProtocol) {
return this;
}

/** Specifies whether TLS v1.0 and 1.1 should be deprecated */
public ProviderBuilder isTlsV1Deprecated(boolean deprecatedTlsV1) {
this.deprecatedTlsV1 = deprecatedTlsV1;
return this;
}

/** Specifies whether TLS v1.0 and 1.1 should be enabled */
public ProviderBuilder isTlsV1Enabled(boolean enabledTlsV1) {
this.enabledTlsV1 = enabledTlsV1;
return this;
}

public Provider build() {
return new OpenSSLProvider(name, provideTrustManager, defaultTlsProtocol);
return new OpenSSLProvider(name, provideTrustManager,
defaultTlsProtocol, deprecatedTlsV1, enabledTlsV1);
}
}

Expand Down
Loading
Loading