Skip to content

Commit

Permalink
Spake
Browse files Browse the repository at this point in the history
Change-Id: I6e5f04c1bbbc53ce9f29ecfd904b1c45ad9c0d78
  • Loading branch information
miguelaranda0 committed Dec 11, 2024
1 parent 9819d22 commit 07c841d
Show file tree
Hide file tree
Showing 10 changed files with 491 additions and 14 deletions.
75 changes: 64 additions & 11 deletions common/src/jni/main/cpp/conscrypt/native_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,7 @@ static jbyteArray ecSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, co

return reinterpret_cast<jbyteArray>(env->CallStaticObjectMethod(
conscrypt::jniutil::cryptoUpcallsClass,
conscrypt::jniutil::cryptoUpcallsClass_rawSignMethod,
privateKey, messageArray.get()));
conscrypt::jniutil::cryptoUpcallsClass_rawSignMethod, privateKey, messageArray.get()));
}

static jbyteArray rsaSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, jint padding,
Expand All @@ -558,10 +557,9 @@ static jbyteArray rsaSignDigestWithPrivateKey(JNIEnv* env, jobject privateKey, j
}

return reinterpret_cast<jbyteArray>(
env->CallStaticObjectMethod(
conscrypt::jniutil::cryptoUpcallsClass,
conscrypt::jniutil::cryptoUpcallsClass_rsaSignMethod,
privateKey, padding, messageArray.get()));
env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass,
conscrypt::jniutil::cryptoUpcallsClass_rsaSignMethod,
privateKey, padding, messageArray.get()));
}

// rsaDecryptWithPrivateKey uses privateKey to decrypt |ciphertext_len| bytes
Expand Down Expand Up @@ -592,10 +590,9 @@ static jbyteArray rsaDecryptWithPrivateKey(JNIEnv* env, jobject privateKey, jint
}

return reinterpret_cast<jbyteArray>(
env->CallStaticObjectMethod(
conscrypt::jniutil::cryptoUpcallsClass,
conscrypt::jniutil::cryptoUpcallsClass_rsaDecryptMethod,
privateKey, padding, ciphertextArray.get()));
env->CallStaticObjectMethod(conscrypt::jniutil::cryptoUpcallsClass,
conscrypt::jniutil::cryptoUpcallsClass_rsaDecryptMethod,
privateKey, padding, ciphertextArray.get()));
}

// *********************************************
Expand Down Expand Up @@ -7266,7 +7263,7 @@ static void info_callback(const SSL* ssl, int type, int value) {

JNI_TRACE("ssl=%p info_callback calling onSSLStateChange", ssl);
env->CallVoidMethod(sslHandshakeCallbacks,
conscrypt::jniutil::sslHandshakeCallbacks_onSSLStateChange, type, value);
conscrypt::jniutil::sslHandshakeCallbacks_onSSLStateChange, type, value);

if (env->ExceptionCheck()) {
JNI_TRACE("ssl=%p info_callback exception", ssl);
Expand Down Expand Up @@ -10891,6 +10888,62 @@ 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,
jint idProverLen, jbyteArray idVerifierArray,
jint idVerifierLen) {
CHECK_ERROR_QUEUE_ON_RETURN;
JNI_TRACE("SPAKE2PLUS_register(%p, %d, %p, %d, %p, %d)", pwArray, pwLen, idProverArray,
idProverLen, idVerifierArray, idVerifierLen);
return {};
}

static jobject NativeCrypto_SSL_CREDENTIAL_new_SPAKE2PLUSV1(JNIEnv* env, jclass) {
CHECK_ERROR_QUEUE_ON_RETURN;
JNI_TRACE("SSL_CREDENTIAL_new_SPAKE2PLUSV1");
return nullptr;
}

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

static void NativeCrypto_SSL_CREDENTIAL_set1_PAKE_client_password_record(JNIEnv* env, jclass,
jobject sslCredential,
jbyteArray password,
jint passwordLen) {
CHECK_ERROR_QUEUE_ON_RETURN;
JNI_TRACE("SSL_CREDENTIAL_set1_PAKE_client_password_record(%p, %p, %d)", sslCredential,
password, passwordLen);
return;
}

static void NativeCrypto_SSL_CREDENTIAL_set1_PAKE_server_password_record(
JNIEnv* env, jclass, jobject sslCredential, jbyteArray password, jint passwordLen,
jbyteArray registration, jint registrationLen) {
CHECK_ERROR_QUEUE_ON_RETURN;
JNI_TRACE("SSL_CREDENTIAL_set1_PAKE_server_password_record(%p, %p, %d, %p, %d)",
sslCredential, password, passwordLen, registration, registrationLen);
return;
}

static void NativeCrypto_SSL_CTX_add1_credential(JNIEnv* env, jclass, jobject sslCtx,
jobject sslCredential) {
CHECK_ERROR_QUEUE_ON_RETURN;
JNI_TRACE("SSL_CTX_add1_credential(%p, %p)", sslCtx, sslCredential);
return;
}

// TESTING METHODS BEGIN

static int NativeCrypto_BIO_read(JNIEnv* env, jclass, jlong bioRef, jbyteArray outputJavaBytes) {
Expand Down
33 changes: 33 additions & 0 deletions common/src/main/java/org/conscrypt/NativeCrypto.java
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,34 @@ static native long X509_CRL_get_nextUpdate(long x509CrlCtx, OpenSSLX509CRL holde

static native int X509_supported_extension(long x509ExtensionRef);

// --- SPAKE ---------------------------------------------------------------

static native Object[] SPAKE2PLUS_register(
byte[] pwArray, int pwLen, byte[] idProverArray,
int idProverLen, byte[] idVerifierArray, int idVerifierLen);

static native Object SSL_CREDENTIAL_new_SPAKE2PLUSV1();

static native void SSL_CREDENTIAL_set1_PAKE_identities(
Object sslCredential,
byte[] context,
int contextLen,
byte[] serverIdentityArray,
int serverIdentityLen,
byte[] clientIdentityArray,
int clientIdentityLen);

static native void SSL_CREDENTIAL_set1_PAKE_client_password_record(
Object sslCredential, byte[] password, int passwordLen);

static native void SSL_CREDENTIAL_set1_PAKE_server_password_record(
Object sslCredential,
byte[] password,
int passwordLen,
byte[] registration,
int registrationLen);

static native int SSL_CTX_add1_credential(Object sslCtx, Object sslCredential);
// --- ASN1_TIME -----------------------------------------------------------

static native void ASN1_TIME_to_Calendar(long asn1TimeCtx, Calendar cal) throws ParsingException;
Expand Down Expand Up @@ -963,6 +991,11 @@ static String cipherSuiteFromJava(String javaCipherSuite) {
"TLS_PSK_WITH_AES_256_CBC_SHA",
};

/** TLS-SPAKE */
static final String[] DEFAULT_SPAKE_CIPHER_SUITES = new String[] {
"TLS1_3_NAMED_PAKE_SPAKE2PLUSV1",
};

static String[] getSupportedCipherSuites() {
return SSLUtils.concat(SUPPORTED_TLS_1_3_CIPHER_SUITES, SUPPORTED_TLS_1_2_CIPHER_SUITES.clone());
}
Expand Down
33 changes: 32 additions & 1 deletion common/src/main/java/org/conscrypt/NativeSsl.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ final class NativeSsl {
private X509Certificate[] localCertificates;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private volatile long ssl;
private final boolean isSpake;

private NativeSsl(long ssl, SSLParametersImpl parameters,
SSLHandshakeCallbacks handshakeCallbacks, AliasChooser aliasChooser,
Expand All @@ -69,6 +70,10 @@ private NativeSsl(long ssl, SSLParametersImpl parameters,
this.handshakeCallbacks = handshakeCallbacks;
this.aliasChooser = aliasChooser;
this.pskCallbacks = pskCallbacks;
this.isSpake = parameters.isSpake();
if (this.isSpake) {
initSpake();
}
}

static NativeSsl newInstance(SSLParametersImpl parameters,
Expand All @@ -86,6 +91,30 @@ BioWrapper newBio() {
}
}

void initSpake() {
SpakeKeyManager spakeKeyManager = parameters.getSpakeKeyManager();
byte[] context = spakeKeyManager.getContext();
byte[] pwArray = spakeKeyManager.getPassword();
byte[] idProverArray = spakeKeyManager.getIdProver();
byte[] idVerifierArray = spakeKeyManager.getIdVerifier();
Object[] result = NativeCrypto.SPAKE2PLUS_register(pwArray, pwArray.length, idProverArray,
idProverArray.length, idVerifierArray, idVerifierArray.length);
byte[] registration = (byte[]) result[2];
long ctx = NativeCrypto.SSL_CTX_new();
Object credential = NativeCrypto.SSL_CREDENTIAL_new_SPAKE2PLUSV1();
NativeCrypto.SSL_CREDENTIAL_set1_PAKE_identities(credential,
context, context.length, idProverArray, idProverArray.length,
idVerifierArray, idVerifierArray.length);
if (isClient()) {
NativeCrypto.SSL_CREDENTIAL_set1_PAKE_client_password_record(credential,
pwArray, pwArray.length);
} else {
NativeCrypto.SSL_CREDENTIAL_set1_PAKE_server_password_record(credential,
pwArray, pwArray.length, registration, registration.length);
}
NativeCrypto.SSL_CTX_add1_credential(ctx, credential);
}

void offerToResumeSession(long sslSessionNativePointer) throws SSLException {
NativeCrypto.SSL_set_session(ssl, this, sslSessionNativePointer);
}
Expand Down Expand Up @@ -349,7 +378,9 @@ void initialize(String hostname, OpenSSLKey channelIdPrivateKey) throws IOExcept
// with TLSv1 and SSLv3).
NativeCrypto.SSL_set_mode(ssl, this, SSL_MODE_CBC_RECORD_SPLITTING);

setCertificateValidation();
if (!isSpake) {
setCertificateValidation();
}
setTlsChannelId(channelIdPrivateKey);
}

Expand Down
3 changes: 3 additions & 0 deletions common/src/main/java/org/conscrypt/OpenSSLProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,9 @@ public OpenSSLProvider(String providerName) {
baseClass + "$X25519_CHACHA20");
put("Alg.Alias.ConscryptHpke.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_GhpkeCHACHA20POLY1305",
"DHKEM_X25519_HKDF_SHA256/HKDF_SHA256/CHACHA20POLY1305");
/* === SPAKE2+ - Conscrypt internal only === */
put("TrustManagerFactory.SPAKE2+", "SpakeTrustManagerFactory");
put("KeyManagerFactory.SPAKE2+", "SpakeKeyManagerFactory");
}

private boolean classExists(String classname) {
Expand Down
54 changes: 52 additions & 2 deletions common/src/main/java/org/conscrypt/SSLParametersImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ final class SSLParametersImpl implements Cloneable {
// source of X.509 certificate based authentication trust decisions or null if not provided
private final X509TrustManager x509TrustManager;

private final SpakeTrustManager spakeTrustManager;
private final SpakeKeyManager spakeKeyManager;

// protocols enabled for SSL connection
String[] enabledProtocols;
// set to indicate when obsolete protocols are filtered
Expand Down Expand Up @@ -131,16 +134,20 @@ final class SSLParametersImpl implements Cloneable {
x509KeyManager = getDefaultX509KeyManager();
// There's no default PSK key manager
pskKeyManager = null;
spakeKeyManager = null;
} else {
x509KeyManager = findFirstX509KeyManager(kms);
pskKeyManager = findFirstPSKKeyManager(kms);
spakeKeyManager = findFirstSpakeKeyManager(kms);
}

// initialize x509TrustManager
if (tms == null) {
x509TrustManager = getDefaultX509TrustManager();
spakeTrustManager = null;
} else {
x509TrustManager = findFirstX509TrustManager(tms);
spakeTrustManager = findFirstSpakeTrustManager(tms);
}

// initialize the list of cipher suites and protocols enabled by default
Expand All @@ -161,7 +168,8 @@ final class SSLParametersImpl implements Cloneable {
boolean x509CipherSuitesNeeded = (x509KeyManager != null) || (x509TrustManager != null);
boolean pskCipherSuitesNeeded = pskKeyManager != null;
enabledCipherSuites = getDefaultCipherSuites(
x509CipherSuitesNeeded, pskCipherSuitesNeeded);
x509CipherSuitesNeeded, pskCipherSuitesNeeded, spakeKeyManager != null);


// We ignore the SecureRandom passed in by the caller. The native code below
// directly accesses /dev/urandom, which makes it irrelevant.
Expand All @@ -180,6 +188,8 @@ private SSLParametersImpl(ClientSessionContext clientSessionContext,
this.x509KeyManager = x509KeyManager;
this.pskKeyManager = pskKeyManager;
this.x509TrustManager = x509TrustManager;
this.spakeKeyManager = null;
this.spakeTrustManager = null;

this.enabledProtocols =
(sslParams.enabledProtocols == null) ? null : sslParams.enabledProtocols.clone();
Expand Down Expand Up @@ -248,6 +258,14 @@ PSKKeyManager getPSKKeyManager() {
return pskKeyManager;
}

/*
* Returns Spake key manager or null for none.
*/
SpakeKeyManager getSpakeKeyManager() {
return spakeKeyManager;
}


/*
* Returns X.509 trust manager or null for none.
*/
Expand Down Expand Up @@ -596,6 +614,18 @@ private static PSKKeyManager findFirstPSKKeyManager(KeyManager[] kms) {
return null;
}

/*
* Returns the first SpakeKeyManager element in the provided array.
*/
private static SpakeKeyManager findFirstSpakeKeyManager(KeyManager[] kms) {
for (KeyManager km : kms) {
if (km instanceof SpakeKeyManager) {
return (SpakeKeyManager)km;
}
}
return null;
}

/*
* Returns the default X.509 trust manager.
*/
Expand Down Expand Up @@ -642,6 +672,18 @@ private static X509TrustManager findFirstX509TrustManager(TrustManager[] tms) {
return null;
}

/*
* Returns the first SpakeTrustManager element in the provided array.
*/
private static SpakeTrustManager findFirstSpakeTrustManager(TrustManager[] tms) {
for (TrustManager tm : tms) {
if (tm instanceof SpakeTrustManager) {
return (SpakeTrustManager) tm;
}
}
return null;
}

String getEndpointIdentificationAlgorithm() {
return endpointIdentificationAlgorithm;
}
Expand Down Expand Up @@ -679,7 +721,11 @@ void setUseCipherSuitesOrder(boolean useCipherSuitesOrder) {

private static String[] getDefaultCipherSuites(
boolean x509CipherSuitesNeeded,
boolean pskCipherSuitesNeeded) {
boolean pskCipherSuitesNeeded,
boolean spakeCipherSuitesNeeded) {
if (spakeCipherSuitesNeeded) {
return NativeCrypto.DEFAULT_SPAKE_CIPHER_SUITES;
}
if (x509CipherSuitesNeeded) {
// X.509 based cipher suites need to be listed.
if (pskCipherSuitesNeeded) {
Expand Down Expand Up @@ -724,4 +770,8 @@ boolean isCTVerificationEnabled(String hostname) {
}
return Platform.isCTVerificationRequired(hostname);
}

boolean isSpake() {
return spakeKeyManager != null;
}
}
Loading

0 comments on commit 07c841d

Please sign in to comment.