WolfSSLSession.getPeerCertificates(): provide full cert chain
This is needed for Certificate Pinning which is a common practice in Android applications.pull/256/head
parent
95bedabeb2
commit
aba417593f
|
@ -2858,9 +2858,29 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_sessionReused
|
||||||
return wolfSSL_session_reused(ssl);
|
return wolfSSL_session_reused(ssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getPeerCertificate
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getPeerCertificateCount
|
||||||
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
|
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
|
||||||
{
|
{
|
||||||
|
#ifdef KEEP_PEER_CERT
|
||||||
|
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
|
||||||
|
(void)jenv;
|
||||||
|
(void)jcl;
|
||||||
|
if (ssl == NULL) {
|
||||||
|
return (jlong)0;
|
||||||
|
}
|
||||||
|
WOLFSSL_X509_CHAIN* chain = wolfSSL_get_peer_chain(ssl);
|
||||||
|
return wolfSSL_get_chain_count(chain);
|
||||||
|
#else
|
||||||
|
(void)jenv;
|
||||||
|
(void)jcl;
|
||||||
|
(void)sslPtr;
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getPeerCertificate
|
||||||
|
(JNIEnv* jenv, jobject jcl, jlong sslPtr, jint index)
|
||||||
|
{
|
||||||
#ifdef KEEP_PEER_CERT
|
#ifdef KEEP_PEER_CERT
|
||||||
WOLFSSL_X509* x509 = NULL;
|
WOLFSSL_X509* x509 = NULL;
|
||||||
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
|
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
|
||||||
|
@ -2870,8 +2890,8 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getPeerCertificate
|
||||||
if (ssl == NULL) {
|
if (ssl == NULL) {
|
||||||
return (jlong)0;
|
return (jlong)0;
|
||||||
}
|
}
|
||||||
|
WOLFSSL_X509_CHAIN* chain = wolfSSL_get_peer_chain(ssl);
|
||||||
x509 = wolfSSL_get_peer_certificate(ssl);
|
x509 = wolfSSL_get_chain_X509(chain, index);
|
||||||
|
|
||||||
return (jlong)(uintptr_t)x509;
|
return (jlong)(uintptr_t)x509;
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -351,13 +351,21 @@ JNIEXPORT jobject JNICALL Java_com_wolfssl_WolfSSLSession_dtlsGetPeer
|
||||||
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_sessionReused
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_sessionReused
|
||||||
(JNIEnv *, jobject, jlong);
|
(JNIEnv *, jobject, jlong);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_wolfssl_WolfSSLSession
|
||||||
|
* Method: getPeerCertificateCount
|
||||||
|
* Signature: (J)I
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getPeerCertificateCount
|
||||||
|
(JNIEnv *, jobject, jlong);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: com_wolfssl_WolfSSLSession
|
* Class: com_wolfssl_WolfSSLSession
|
||||||
* Method: getPeerCertificate
|
* Method: getPeerCertificate
|
||||||
* Signature: (J)J
|
* Signature: (JI)J
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getPeerCertificate
|
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getPeerCertificate
|
||||||
(JNIEnv *, jobject, jlong);
|
(JNIEnv *, jobject, jlong, jint);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: com_wolfssl_WolfSSLSession
|
* Class: com_wolfssl_WolfSSLSession
|
||||||
|
|
|
@ -358,7 +358,8 @@ public class WolfSSLSession {
|
||||||
private native long getDtlsReplayDropCount(long ssl);
|
private native long getDtlsReplayDropCount(long ssl);
|
||||||
private native InetSocketAddress dtlsGetPeer(long ssl);
|
private native InetSocketAddress dtlsGetPeer(long ssl);
|
||||||
private native int sessionReused(long ssl);
|
private native int sessionReused(long ssl);
|
||||||
private native long getPeerCertificate(long ssl);
|
private native int getPeerCertificateCount(long ssl);
|
||||||
|
private native long getPeerCertificate(long ssl, int index);
|
||||||
private native String getPeerX509Issuer(long ssl, long x509);
|
private native String getPeerX509Issuer(long ssl, long x509);
|
||||||
private native String getPeerX509Subject(long ssl, long x509);
|
private native String getPeerX509Subject(long ssl, long x509);
|
||||||
private native String getPeerX509AltName(long ssl, long x509);
|
private native String getPeerX509AltName(long ssl, long x509);
|
||||||
|
@ -2590,6 +2591,27 @@ public class WolfSSLSession {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of certificates in the peer's certificate chain.
|
||||||
|
*
|
||||||
|
* @return number of certificates in the peer's certificate chain.
|
||||||
|
* @throws IllegalStateException WolfSSLContext has been freed
|
||||||
|
* @throws WolfSSLJNIException Internal JNI error
|
||||||
|
* @see WolfSSLSession#getPeerCertificate(int)
|
||||||
|
*/
|
||||||
|
public int getPeerCertificateCount()
|
||||||
|
throws IllegalStateException, WolfSSLJNIException {
|
||||||
|
|
||||||
|
confirmObjectIsActive();
|
||||||
|
|
||||||
|
synchronized (sslLock) {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
|
||||||
|
WolfSSLDebug.INFO, this.sslPtr, "entered getPeerCertificateCount()");
|
||||||
|
|
||||||
|
return getPeerCertificateCount(this.sslPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the native (long) WOLFSSL_X509 pointer to the peer's certificate.
|
* Gets the native (long) WOLFSSL_X509 pointer to the peer's certificate.
|
||||||
* This can be used to retrieve further information about the peer's
|
* This can be used to retrieve further information about the peer's
|
||||||
|
@ -2606,6 +2628,7 @@ public class WolfSSLSession {
|
||||||
* Pointer should be freed by calling:
|
* Pointer should be freed by calling:
|
||||||
* WolfSSLCertificate.freeX509(long x509);
|
* WolfSSLCertificate.freeX509(long x509);
|
||||||
*
|
*
|
||||||
|
* @param index index of the certificate in the peer's certificate chain
|
||||||
* @return (long) WOLFSSL_X509 pointer to the peer's certificate.
|
* @return (long) WOLFSSL_X509 pointer to the peer's certificate.
|
||||||
* @throws IllegalStateException WolfSSLContext has been freed
|
* @throws IllegalStateException WolfSSLContext has been freed
|
||||||
* @throws WolfSSLJNIException Internal JNI error
|
* @throws WolfSSLJNIException Internal JNI error
|
||||||
|
@ -2614,7 +2637,7 @@ public class WolfSSLSession {
|
||||||
* @see WolfSSLSession#getVersion()
|
* @see WolfSSLSession#getVersion()
|
||||||
* @see WolfSSLSession#getCurrentCipher()
|
* @see WolfSSLSession#getCurrentCipher()
|
||||||
*/
|
*/
|
||||||
public long getPeerCertificate()
|
public long getPeerCertificate(int index)
|
||||||
throws IllegalStateException, WolfSSLJNIException {
|
throws IllegalStateException, WolfSSLJNIException {
|
||||||
|
|
||||||
confirmObjectIsActive();
|
confirmObjectIsActive();
|
||||||
|
@ -2623,7 +2646,7 @@ public class WolfSSLSession {
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
|
||||||
WolfSSLDebug.INFO, this.sslPtr, "entered getPeerCertificate()");
|
WolfSSLDebug.INFO, this.sslPtr, "entered getPeerCertificate()");
|
||||||
|
|
||||||
return getPeerCertificate(this.sslPtr);
|
return getPeerCertificate(this.sslPtr, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -516,17 +516,13 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession
|
||||||
"SSLSocket/Engine closed");
|
"SSLSocket/Engine closed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int numCerts;
|
||||||
try {
|
try {
|
||||||
x509 = this.ssl.getPeerCertificate();
|
numCerts = this.ssl.getPeerCertificateCount();
|
||||||
} catch (IllegalStateException | WolfSSLJNIException ex) {
|
} catch (IllegalStateException | WolfSSLJNIException ex) {
|
||||||
Logger.getLogger(
|
Logger.getLogger(
|
||||||
WolfSSLImplementSSLSession.class.getName()).log(
|
WolfSSLImplementSSLSession.class.getName()).log(
|
||||||
Level.SEVERE, null, ex);
|
Level.SEVERE, null, ex);
|
||||||
x509 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if no peer cert, throw SSLPeerUnverifiedException */
|
|
||||||
if (x509 == 0) {
|
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"ssl.getPeerCertificates() returned null, trying cached cert");
|
"ssl.getPeerCertificates() returned null, trying cached cert");
|
||||||
|
|
||||||
|
@ -542,56 +538,88 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession
|
||||||
throw new SSLPeerUnverifiedException("No peer certificate");
|
throw new SSLPeerUnverifiedException("No peer certificate");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
X509Certificate[] certs = new X509Certificate[numCerts];
|
||||||
|
|
||||||
try {
|
for (int i = 0; i < numCerts; i++) {
|
||||||
/* wolfSSL starting with 5.3.0 returns a new WOLFSSL_X509
|
try {
|
||||||
* structure from wolfSSL_get_peer_certificate(). In that case,
|
x509 = this.ssl.getPeerCertificate(i);
|
||||||
* we need to free the pointer when finished. Prior to 5.3.0,
|
} catch (IllegalStateException | WolfSSLJNIException ex) {
|
||||||
* this memory was freed internally by wolfSSL since the API
|
Logger.getLogger(
|
||||||
* only returned a pointer to internal memory */
|
WolfSSLImplementSSLSession.class.getName()).log(
|
||||||
if (WolfSSL.getLibVersionHex() >= 0x05003000) {
|
Level.SEVERE, null, ex);
|
||||||
cert = new WolfSSLX509(x509, true);
|
x509 = 0;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
cert = new WolfSSLX509(x509, false);
|
/* if no peer cert, throw SSLPeerUnverifiedException */
|
||||||
|
if (x509 == 0) {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"ssl.getPeerCertificates() returned null, trying cached cert");
|
||||||
|
|
||||||
|
if (this.peerCerts != null) {
|
||||||
|
/* If peer cert is already cached, just return that */
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"peer cert already cached, returning it");
|
||||||
|
return this.peerCerts.clone();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"No peer cert sent and none cached");
|
||||||
|
throw new SSLPeerUnverifiedException("No peer certificate");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (WolfSSLException ex) {
|
|
||||||
throw new SSLPeerUnverifiedException("Error creating certificate");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* convert WolfSSLX509 into X509Certificate so we can release
|
try {
|
||||||
* our native memory */
|
/* wolfSSL starting with 5.3.0 returns a new WOLFSSL_X509
|
||||||
try {
|
* structure from wolfSSL_get_peer_certificate(). In that case,
|
||||||
cf = CertificateFactory.getInstance("X.509");
|
* we need to free the pointer when finished. Prior to 5.3.0,
|
||||||
} catch (CertificateException ex) {
|
* this memory was freed internally by wolfSSL since the API
|
||||||
|
* only returned a pointer to internal memory */
|
||||||
|
if (WolfSSL.getLibVersionHex() >= 0x05003000) {
|
||||||
|
cert = new WolfSSLX509(x509, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cert = new WolfSSLX509(x509, false);
|
||||||
|
}
|
||||||
|
} catch (WolfSSLException ex) {
|
||||||
|
throw new SSLPeerUnverifiedException("Error creating certificate");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert WolfSSLX509 into X509Certificate so we can release
|
||||||
|
* our native memory */
|
||||||
|
try {
|
||||||
|
cf = CertificateFactory.getInstance("X.509");
|
||||||
|
} catch (CertificateException ex) {
|
||||||
|
cert.free();
|
||||||
|
throw new SSLPeerUnverifiedException(
|
||||||
|
"Error getting CertificateFactory instance");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
der = new ByteArrayInputStream(cert.getEncoded());
|
||||||
|
} catch (CertificateEncodingException ex) {
|
||||||
|
cert.free();
|
||||||
|
throw new SSLPeerUnverifiedException(
|
||||||
|
"Error getting encoded DER from WolfSSLX509 object");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
exportCert = (X509Certificate)cf.generateCertificate(der);
|
||||||
|
} catch (CertificateException ex) {
|
||||||
|
cert.free();
|
||||||
|
throw new SSLPeerUnverifiedException(
|
||||||
|
"Error generating X509Certificdate from DER encoding");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release native memory */
|
||||||
cert.free();
|
cert.free();
|
||||||
throw new SSLPeerUnverifiedException(
|
|
||||||
"Error getting CertificateFactory instance");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
certs[i] = exportCert;
|
||||||
der = new ByteArrayInputStream(cert.getEncoded());
|
|
||||||
} catch (CertificateEncodingException ex) {
|
|
||||||
cert.free();
|
|
||||||
throw new SSLPeerUnverifiedException(
|
|
||||||
"Error getting encoded DER from WolfSSLX509 object");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
exportCert = (X509Certificate)cf.generateCertificate(der);
|
|
||||||
} catch (CertificateException ex) {
|
|
||||||
cert.free();
|
|
||||||
throw new SSLPeerUnverifiedException(
|
|
||||||
"Error generating X509Certificdate from DER encoding");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* release native memory */
|
|
||||||
cert.free();
|
|
||||||
|
|
||||||
/* cache peer cert for use by app in resumed session */
|
/* cache peer cert for use by app in resumed session */
|
||||||
this.peerCerts = new X509Certificate[] { exportCert };
|
this.peerCerts = certs;
|
||||||
|
|
||||||
return this.peerCerts.clone();
|
return certs.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -612,25 +640,30 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
peerX509 = this.ssl.getPeerCertificate();
|
int numCerts = this.ssl.getPeerCertificateCount();
|
||||||
if (peerX509 == 0) {
|
javax.security.cert.X509Certificate[] certs = new javax.security.cert.X509Certificate[numCerts];
|
||||||
return null;
|
|
||||||
|
for (int i = 0; i < numCerts; i++) {
|
||||||
|
peerX509 = this.ssl.getPeerCertificate(i);
|
||||||
|
if (peerX509 == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wolfSSL starting with 5.3.0 returns a new WOLFSSL_X509
|
||||||
|
* structure from wolfSSL_get_peer_certificate(). In that case,
|
||||||
|
* we need to free the pointer when finished. Prior to 5.3.0,
|
||||||
|
* this memory was freed internally by wolfSSL since the API
|
||||||
|
* only returned a pointer to internal memory */
|
||||||
|
if (WolfSSL.getLibVersionHex() >= 0x05003000) {
|
||||||
|
x509 = new WolfSSLX509X(peerX509, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
x509 = new WolfSSLX509X(peerX509, false);
|
||||||
|
}
|
||||||
|
certs[i] = (javax.security.cert.X509Certificate)x509;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wolfSSL starting with 5.3.0 returns a new WOLFSSL_X509
|
return certs;
|
||||||
* structure from wolfSSL_get_peer_certificate(). In that case,
|
|
||||||
* we need to free the pointer when finished. Prior to 5.3.0,
|
|
||||||
* this memory was freed internally by wolfSSL since the API
|
|
||||||
* only returned a pointer to internal memory */
|
|
||||||
if (WolfSSL.getLibVersionHex() >= 0x05003000) {
|
|
||||||
x509 = new WolfSSLX509X(peerX509, true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
x509 = new WolfSSLX509X(peerX509, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new javax.security.cert.X509Certificate[] {
|
|
||||||
(javax.security.cert.X509Certificate)x509 };
|
|
||||||
|
|
||||||
} catch (IllegalStateException | WolfSSLJNIException |
|
} catch (IllegalStateException | WolfSSLJNIException |
|
||||||
WolfSSLException ex) {
|
WolfSSLException ex) {
|
||||||
|
@ -654,7 +687,7 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
peerX509 = this.ssl.getPeerCertificate();
|
peerX509 = this.ssl.getPeerCertificate(0);
|
||||||
if (peerX509 == 0) {
|
if (peerX509 == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue