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

Free WOLFSSL_X509 from wolfSSL_get_peer_certificate() with wolfSSL >= 5.3.0 #188

Merged
merged 1 commit into from
Apr 17, 2024
Merged
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
12 changes: 10 additions & 2 deletions examples/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLSession;
import com.wolfssl.WolfSSLContext;
import com.wolfssl.WolfSSLCertificate;
import com.wolfssl.WolfSSLException;
import com.wolfssl.WolfSSLJNIException;
import com.wolfssl.WolfSSLIOSendCallback;
Expand Down Expand Up @@ -722,11 +723,11 @@ public void run(String[] args) {

void showPeer(WolfSSLSession ssl) {

long peerCrtPtr = 0;
String altname;

try {

long peerCrtPtr = ssl.getPeerCertificate();
peerCrtPtr = ssl.getPeerCertificate();

if (peerCrtPtr != 0) {
System.out.println("issuer : " +
Expand All @@ -743,6 +744,13 @@ void showPeer(WolfSSLSession ssl) {

} catch (WolfSSLJNIException e) {
e.printStackTrace();

} finally {
if (WolfSSL.getLibVersionHex() >= 0x05003000) {
if (peerCrtPtr != 0) {
WolfSSLCertificate.freeX509(peerCrtPtr);
}
}
}
}

Expand Down
10 changes: 9 additions & 1 deletion examples/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLSession;
import com.wolfssl.WolfSSLContext;
import com.wolfssl.WolfSSLCertificate;
import com.wolfssl.WolfSSLException;
import com.wolfssl.WolfSSLJNIException;
import com.wolfssl.WolfSSLIOSendCallback;
Expand Down Expand Up @@ -618,7 +619,7 @@ public void run(String[] args) {
void showPeer(WolfSSLSession ssl) {

String altname;
long peerCrtPtr;
long peerCrtPtr = 0;

try {

Expand All @@ -643,6 +644,13 @@ void showPeer(WolfSSLSession ssl) {

} catch (WolfSSLJNIException e) {
e.printStackTrace();

} finally {
if (WolfSSL.getLibVersionHex() >= 0x05003000) {
if (peerCrtPtr != 0) {
WolfSSLCertificate.freeX509(peerCrtPtr);
}
}
}
}

Expand Down
42 changes: 38 additions & 4 deletions src/java/com/wolfssl/WolfSSLCertificate.java
Original file line number Diff line number Diff line change
Expand Up @@ -277,19 +277,29 @@ public WolfSSLCertificate(String fileName, int format)
* Create WolfSSLCertificate from pre existing native pointer.
*
* @param x509 pre existing native pointer to WOLFSSL_X509 structure.
* @param doFree should this WOLFSSL_X509 structure be freed when free()
* is called? true to free memory, false to skip free. Free
* should be skipped if caller is controlling memory for this
* WOLFSSL_X509 struct pointer.
*
* @throws WolfSSLException if input pointer is invalid
*/
public WolfSSLCertificate(long x509) throws WolfSSLException {
public WolfSSLCertificate(long x509, boolean doFree)
throws WolfSSLException {

if (x509 == 0) {
throw new WolfSSLException("Input pointer may not be 0/NULL");
}
x509Ptr = x509;

/* x509Ptr has NOT been allocated natively, do not mark as owned.
* Original owner is responsible for freeing. */
this.weOwnX509Ptr = false;
if (!doFree) {
/* x509Ptr has NOT been allocated natively, do not mark as owned.
* Original owner is responsible for freeing. */
this.weOwnX509Ptr = false;
}
else {
this.weOwnX509Ptr = true;
}

synchronized (stateLock) {
this.active = true;
Expand Down Expand Up @@ -1498,6 +1508,30 @@ public X509Certificate getX509Certificate()
return cert;
}

/**
* Free native WOLFSSL_X509 structure pointer.
* This method should be called with caution, so that double free
* issues do not happen. Calling code should take extra caution to ensure
* control is maintained around this native pointer and synchronization
* is used correctly to ensure multiple threads will not free the same
* pointer simultaneously.
*
* This method is needed when WolfSSLSession.getPeerCertificate()
* is called with wolfSSL versions later than or equal to 5.3.0.
* See wolfSSL PR 4807.
*
* @param x509 pointer to initialized WOLFSSL_X509 structure to be freed
* by calling wolfSSL_X509_free() at the JNI level.
*/
public static void freeX509(long x509) {

/* No object active check or synchronization needed, since this
* method is working on a standalone pointer, not related to this
* object. Method placed here since it relates to common
* WOLFSSL_X509 / WolfSSLCertificate functionality */
X509_free(x509);
}

@Override
public String toString() {

Expand Down
11 changes: 11 additions & 0 deletions src/java/com/wolfssl/WolfSSLSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -1796,6 +1796,17 @@ public int sessionReused()
* This can be used to retrieve further information about the peer's
* certificate (issuer, subject, alt name, etc.)
*
* wolfSSL versions 5.3.0 or later return a newly-allocated
* WOLFSSL_X509 structure poiner from the native
* wolfSSL_get_peer_certificate() API called by this wrapper. If using
* wolfSSL greater than or equal to 5.3.0, the pointer (long) returned
* from this method must be freed by the caller. Versions of wolfSSL
* less than 5.3.0 should not free the pointer returned since it points
* to internal memory that is freed by native wolfSSL.
*
* Pointer should be freed by calling:
* WolfSSLCertificate.freeX509(long x509);
*
* @return (long) WOLFSSL_X509 pointer to the peer's certificate.
* @throws IllegalStateException WolfSSLContext has been freed
* @throws WolfSSLJNIException Internal JNI error
Expand Down
62 changes: 56 additions & 6 deletions src/java/com/wolfssl/provider/jsse/WolfSSLImplementSSLSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,17 @@ public synchronized Certificate[] getPeerCertificates()
}

try {
cert = new WolfSSLX509(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) {
cert = new WolfSSLX509(x509, true);
}
else {
cert = new WolfSSLX509(x509, false);
}
} catch (WolfSSLException ex) {
throw new SSLPeerUnverifiedException("Error creating certificate");
}
Expand Down Expand Up @@ -529,14 +539,32 @@ public Certificate[] getLocalCertificates() {
@Override
public synchronized javax.security.cert.X509Certificate[] getPeerCertificateChain()
throws SSLPeerUnverifiedException {

long peerX509 = 0;
WolfSSLX509X x509;

if (ssl == null) {
throw new SSLPeerUnverifiedException("handshake not done");
}

try {
x509 = new WolfSSLX509X(this.ssl.getPeerCertificate());
peerX509 = this.ssl.getPeerCertificate();
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);
}

return new javax.security.cert.X509Certificate[] {
(javax.security.cert.X509Certificate)x509 };

Expand All @@ -552,15 +580,37 @@ public synchronized javax.security.cert.X509Certificate[] getPeerCertificateChai
@Override
public synchronized Principal getPeerPrincipal()
throws SSLPeerUnverifiedException {

long peerX509 = 0;
Principal peerPrincipal = null;
WolfSSLX509 x509 = null;

if (ssl == null) {
throw new SSLPeerUnverifiedException("handshake not done");
}

try {
Principal peerPrincipal = null;
WolfSSLX509 x509 = new WolfSSLX509(this.ssl.getPeerCertificate());
peerPrincipal = x509.getSubjectDN();
x509.free();
peerX509 = this.ssl.getPeerCertificate();
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 WolfSSLX509(peerX509, true);
}
else {
x509 = new WolfSSLX509(peerX509, false);
}

if (x509 != null) {
peerPrincipal = x509.getSubjectDN();
x509.free();
}

return peerPrincipal;

Expand Down
10 changes: 7 additions & 3 deletions src/java/com/wolfssl/provider/jsse/WolfSSLX509.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,19 @@ public WolfSSLX509(String derName) throws WolfSSLException {
* Create new WolfSSLX509 object
*
* @param x509 initialized pointer to native WOLFSSL_X509 struct
* @param doFree should this WOLFSSL_X509 structure be freed when free()
* is called? true to free memory, false to skip free. Free
* should be skipped if caller is controlling memory for this
* WOLFSSL_X509 struct pointer.
*
* @throws WolfSSLException if certificate parsing fails
*/
public WolfSSLX509(long x509) throws WolfSSLException {
public WolfSSLX509(long x509, boolean doFree) throws WolfSSLException {
super();
this.cert = new WolfSSLCertificate(x509);
this.cert = new WolfSSLCertificate(x509, doFree);

WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"created new WolfSSLX509(long x509)");
"created new WolfSSLX509(long x509, boolean doFree)");
}

@Override
Expand Down
10 changes: 7 additions & 3 deletions src/java/com/wolfssl/provider/jsse/WolfSSLX509X.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,19 @@ public WolfSSLX509X(String derName) throws WolfSSLException {
* Create new WolfSSLX509X object
*
* @param x509 initialized pointer to native WOLFSSL_X509 struct
* @param doFree should this WOLFSSL_X509 structure be freed when free()
* is called? true to free memory, false to skip free. Free
* should be skipped if caller is controlling memory for this
* WOLFSSL_X509 struct pointer.
*
* @throws WolfSSLException if certificate parsing fails
*/
public WolfSSLX509X(long x509) throws WolfSSLException {
public WolfSSLX509X(long x509, boolean doFree) throws WolfSSLException {

WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"created new WolfSSLX509X(long x509)");
"created new WolfSSLX509X(long x509, boolean doFree)");

this.cert = new WolfSSLX509(x509);
this.cert = new WolfSSLX509(x509, doFree);
}

@Override
Expand Down