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);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getPeerCertificate
|
||||
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getPeerCertificateCount
|
||||
(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
|
||||
WOLFSSL_X509* x509 = NULL;
|
||||
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
|
||||
|
@ -2870,8 +2890,8 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getPeerCertificate
|
|||
if (ssl == NULL) {
|
||||
return (jlong)0;
|
||||
}
|
||||
|
||||
x509 = wolfSSL_get_peer_certificate(ssl);
|
||||
WOLFSSL_X509_CHAIN* chain = wolfSSL_get_peer_chain(ssl);
|
||||
x509 = wolfSSL_get_chain_X509(chain, index);
|
||||
|
||||
return (jlong)(uintptr_t)x509;
|
||||
#else
|
||||
|
|
|
@ -351,13 +351,21 @@ JNIEXPORT jobject JNICALL Java_com_wolfssl_WolfSSLSession_dtlsGetPeer
|
|||
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_sessionReused
|
||||
(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
|
||||
* Method: getPeerCertificate
|
||||
* Signature: (J)J
|
||||
* Signature: (JI)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getPeerCertificate
|
||||
(JNIEnv *, jobject, jlong);
|
||||
(JNIEnv *, jobject, jlong, jint);
|
||||
|
||||
/*
|
||||
* Class: com_wolfssl_WolfSSLSession
|
||||
|
|
|
@ -358,7 +358,8 @@ public class WolfSSLSession {
|
|||
private native long getDtlsReplayDropCount(long ssl);
|
||||
private native InetSocketAddress dtlsGetPeer(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 getPeerX509Subject(long ssl, long x509);
|
||||
private native String getPeerX509AltName(long ssl, long x509);
|
||||
|
@ -2590,6 +2591,27 @@ public class WolfSSLSession {
|
|||
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.
|
||||
* 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:
|
||||
* 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.
|
||||
* @throws IllegalStateException WolfSSLContext has been freed
|
||||
* @throws WolfSSLJNIException Internal JNI error
|
||||
|
@ -2614,7 +2637,7 @@ public class WolfSSLSession {
|
|||
* @see WolfSSLSession#getVersion()
|
||||
* @see WolfSSLSession#getCurrentCipher()
|
||||
*/
|
||||
public long getPeerCertificate()
|
||||
public long getPeerCertificate(int index)
|
||||
throws IllegalStateException, WolfSSLJNIException {
|
||||
|
||||
confirmObjectIsActive();
|
||||
|
@ -2623,7 +2646,7 @@ public class WolfSSLSession {
|
|||
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
|
||||
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");
|
||||
}
|
||||
|
||||
int numCerts;
|
||||
try {
|
||||
x509 = this.ssl.getPeerCertificate();
|
||||
numCerts = this.ssl.getPeerCertificateCount();
|
||||
} catch (IllegalStateException | WolfSSLJNIException ex) {
|
||||
Logger.getLogger(
|
||||
WolfSSLImplementSSLSession.class.getName()).log(
|
||||
Level.SEVERE, null, ex);
|
||||
x509 = 0;
|
||||
}
|
||||
|
||||
/* if no peer cert, throw SSLPeerUnverifiedException */
|
||||
if (x509 == 0) {
|
||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||
"ssl.getPeerCertificates() returned null, trying cached cert");
|
||||
|
||||
|
@ -542,56 +538,88 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession
|
|||
throw new SSLPeerUnverifiedException("No peer certificate");
|
||||
}
|
||||
}
|
||||
X509Certificate[] certs = new X509Certificate[numCerts];
|
||||
|
||||
try {
|
||||
/* 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) {
|
||||
cert = new WolfSSLX509(x509, true);
|
||||
for (int i = 0; i < numCerts; i++) {
|
||||
try {
|
||||
x509 = this.ssl.getPeerCertificate(i);
|
||||
} catch (IllegalStateException | WolfSSLJNIException ex) {
|
||||
Logger.getLogger(
|
||||
WolfSSLImplementSSLSession.class.getName()).log(
|
||||
Level.SEVERE, null, ex);
|
||||
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
|
||||
* our native memory */
|
||||
try {
|
||||
cf = CertificateFactory.getInstance("X.509");
|
||||
} catch (CertificateException ex) {
|
||||
try {
|
||||
/* 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) {
|
||||
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();
|
||||
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");
|
||||
certs[i] = exportCert;
|
||||
}
|
||||
|
||||
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 */
|
||||
this.peerCerts = new X509Certificate[] { exportCert };
|
||||
this.peerCerts = certs;
|
||||
|
||||
return this.peerCerts.clone();
|
||||
return certs.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -612,25 +640,30 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession
|
|||
}
|
||||
|
||||
try {
|
||||
peerX509 = this.ssl.getPeerCertificate();
|
||||
if (peerX509 == 0) {
|
||||
return null;
|
||||
int numCerts = this.ssl.getPeerCertificateCount();
|
||||
javax.security.cert.X509Certificate[] certs = new javax.security.cert.X509Certificate[numCerts];
|
||||
|
||||
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
|
||||
* 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 };
|
||||
return certs;
|
||||
|
||||
} catch (IllegalStateException | WolfSSLJNIException |
|
||||
WolfSSLException ex) {
|
||||
|
@ -654,7 +687,7 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession
|
|||
}
|
||||
|
||||
try {
|
||||
peerX509 = this.ssl.getPeerCertificate();
|
||||
peerX509 = this.ssl.getPeerCertificate(0);
|
||||
if (peerX509 == 0) {
|
||||
return null;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue