Skip to content
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
25 changes: 23 additions & 2 deletions native/com_wolfssl_WolfSSLCertRequest.c
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1add_1ext_1via_1
}

JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1add_1ext_1via_1set_1object_1boolean
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr, jint nid, jboolean extValue, jboolean isCritical)
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr, jint nid, jboolean extValue, jboolean isCritical, jint pathLen)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509ReqPtr;
Expand All @@ -672,6 +672,17 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1add_1ext_1via_1
return WOLFSSL_FAILURE;
}

/* pathLen >= 0 requires wolfSSL > 5.8.4 which includes fixes so
* wolfSSL_ASN1_OBJECT_dup() copies pathlen and wolfSSL_X509_add_ext()
* correctly sets pathLengthSet for DER encoding. Without these fixes,
* pathLen is silently dropped during cert generation. */
if (pathLen >= 0) {
#if !((LIBWOLFSSL_VERSION_HEX > 0x05008004) || \
defined(WOLFSSL_PR9940_PATCH_APPLIED))
return (jint)NOT_COMPILED_IN;
#endif
}

ext = wolfSSL_X509_EXTENSION_new();
if (ext == NULL) {
ret = WOLFSSL_FAILURE;
Expand Down Expand Up @@ -699,6 +710,16 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1add_1ext_1via_1
}
}

if (ret == WOLFSSL_SUCCESS && pathLen >= 0) {
obj->pathlen = wolfSSL_ASN1_INTEGER_new();
if (obj->pathlen == NULL) {
ret = WOLFSSL_FAILURE;
}
else {
obj->pathlen->length = pathLen;
Comment thread
cconlon marked this conversation as resolved.
Comment thread
cconlon marked this conversation as resolved.
}
}

if (ret == WOLFSSL_SUCCESS) {
ret = wolfSSL_X509_EXTENSION_set_object(ext, obj);
}
Expand All @@ -707,7 +728,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1add_1ext_1via_1
ret = wolfSSL_X509_add_ext(x509, ext, -1);
}


if (obj != NULL) {
wolfSSL_ASN1_OBJECT_free(obj);
}
Expand All @@ -723,6 +743,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1add_1ext_1via_1
(void)nid;
(void)extValue;
(void)isCritical;
(void)pathLen;
return (jint)NOT_COMPILED_IN;
#endif
}
Expand Down
4 changes: 2 additions & 2 deletions native/com_wolfssl_WolfSSLCertRequest.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 23 additions & 2 deletions native/com_wolfssl_WolfSSLCertificate.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1add_1ext_1via_1
}

JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1add_1ext_1via_1set_1object_1boolean
(JNIEnv* jenv, jclass jcl, jlong x509Ptr, jint nid, jboolean extValue, jboolean isCritical)
(JNIEnv* jenv, jclass jcl, jlong x509Ptr, jint nid, jboolean extValue, jboolean isCritical, jint pathLen)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr;
Expand All @@ -378,6 +378,17 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1add_1ext_1via_1
return WOLFSSL_FAILURE;
}

/* pathLen >= 0 requires wolfSSL > 5.8.4 which includes fixes so
* wolfSSL_ASN1_OBJECT_dup() copies pathlen and wolfSSL_X509_add_ext()
* correctly sets pathLengthSet for DER encoding. Without these fixes,
* pathLen is silently dropped during cert generation. */
if (pathLen >= 0) {
#if !((LIBWOLFSSL_VERSION_HEX > 0x05008004) || \
defined(WOLFSSL_PR9940_PATCH_APPLIED))
return (jint)NOT_COMPILED_IN;
#endif
}

ext = wolfSSL_X509_EXTENSION_new();
if (ext == NULL) {
ret = WOLFSSL_FAILURE;
Expand Down Expand Up @@ -405,6 +416,16 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1add_1ext_1via_1
}
}

if (ret == WOLFSSL_SUCCESS && pathLen >= 0) {
obj->pathlen = wolfSSL_ASN1_INTEGER_new();
if (obj->pathlen == NULL) {
ret = WOLFSSL_FAILURE;
}
else {
obj->pathlen->length = pathLen;
Comment thread
cconlon marked this conversation as resolved.
}
}

if (ret == WOLFSSL_SUCCESS) {
ret = wolfSSL_X509_EXTENSION_set_object(ext, obj);
}
Expand All @@ -413,7 +434,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1add_1ext_1via_1
ret = wolfSSL_X509_add_ext(x509, ext, -1);
}


if (obj != NULL) {
wolfSSL_ASN1_OBJECT_free(obj);
}
Expand All @@ -429,6 +449,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1add_1ext_1via_1
(void)nid;
(void)extValue;
(void)isCritical;
(void)pathLen;
return (jint)NOT_COMPILED_IN;
#endif
}
Expand Down
4 changes: 2 additions & 2 deletions native/com_wolfssl_WolfSSLCertificate.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 52 additions & 5 deletions src/java/com/wolfssl/WolfSSLCertRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ static native int X509_REQ_set_pubkey_native_open(long x509ReqPtr,
static native int X509_add_ext_via_nconf_nid(long x509Ptr, int nid,
String extValue, boolean isCritical);
static native int X509_add_ext_via_set_object_boolean(long x509Ptr,
int nid, boolean extValue, boolean isCritical);
int nid, boolean extValue, boolean isCritical, int pathLen);

/**
* Create new empty WolfSSLCertRequest object, for use with CSR generation
Expand Down Expand Up @@ -506,6 +506,36 @@ public void addExtension(int nid, String value, boolean isCritical)
public void addExtension(int nid, boolean value, boolean isCritical)
throws IllegalStateException, WolfSSLException {

addExtension(nid, value, -1, isCritical);
}

/**
* Add Basic Constraints extension with CA flag and path length constraint
* to a WolfSSLCertRequest.
*
* This method allows setting the Basic Constraints extension with both the
* CA boolean and an optional path length constraint. The path length limits
* the number of intermediate CA certificates that may follow this
* certificate in a valid certification path.
*
* To set Basic Constraints without a path length constraint, use
* {@link #addExtension(int, boolean, boolean)} with
* {@code WolfSSL.NID_basic_constraints} instead.
*
* @param nid NID of extension to add. Must be:
* WolfSSL.NID_basic_constraints
* @param value Boolean value of CA flag (true for CA, false for end entity)
* @param pathLen Maximum number of intermediate CA certificates allowed
* below this CA. Must be >= 0, or -1 to not set a path length
* constraint. Only meaningful when value is true.
* @param isCritical Boolean flag indicating if this extension is critical
*
* @throws IllegalStateException if WolfSSLCertRequest has been freed
* @throws WolfSSLException if invalid arguments or on native JNI error
*/
public void addExtension(int nid, boolean value, int pathLen,
boolean isCritical) throws IllegalStateException, WolfSSLException {

int ret = 0;

confirmObjectIsActive();
Expand All @@ -514,20 +544,37 @@ public void addExtension(int nid, boolean value, boolean isCritical)
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr,
() -> "entered addExtension(nid: " + nid + ", value: " + value +
", isCritical: " + isCritical + ")");
", pathLen: " + pathLen + ", isCritical: " + isCritical + ")");
}

if (nid != WolfSSL.NID_basic_constraints) {
throw new WolfSSLException(
"Unsupported X509v3 extension NID: " + nid);
}

if (pathLen < -1) {
throw new WolfSSLException(
"Path length must be >= 0 or -1, got: " + pathLen);
}

Comment thread
cconlon marked this conversation as resolved.
if (!value && pathLen >= 0) {
throw new WolfSSLException(
"pathLen must not be set when isCA is FALSE (RFC 5280), " +
"got pathLen: " + pathLen);
}

synchronized (x509ReqLock) {
ret = X509_add_ext_via_set_object_boolean(
this.x509ReqPtr, nid, value, isCritical);
ret = X509_add_ext_via_set_object_boolean(this.x509ReqPtr, nid,
value, isCritical, pathLen);
}

if (ret != WolfSSL.SSL_SUCCESS) {
if (ret == WolfSSL.NOT_COMPILED_IN) {
throw new WolfSSLException(
"addExtension NOT_COMPILED_IN, pathLen " +
"support requires wolfSSL > 5.8.4 or " +
"PR 9940 patch (ret: " + ret + ")");
Comment thread
cconlon marked this conversation as resolved.
}
else if (ret != WolfSSL.SSL_SUCCESS) {
throw new WolfSSLException(
"Error setting extension into native WOLFSSL_X509 " +
"(ret: " + ret + ")");
Expand Down
58 changes: 53 additions & 5 deletions src/java/com/wolfssl/WolfSSLCertificate.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ static native int X509_set_pubkey_native_open(long x509Ptr, int keyType,
static native int X509_add_ext_via_nconf_nid(long x509Ptr, int nid,
String extValue, boolean isCritical);
static native int X509_add_ext_via_set_object_boolean(long x509Ptr,
int nid, boolean extValue, boolean isCritical);
int nid, boolean extValue, boolean isCritical, int pathLen);
static native int X509_set_notBefore(long x509Ptr, long timeSecs);
static native int X509_set_notAfter(long x509Ptr, long timeSecs);
static native int X509_set_serialNumber(long x509Ptr, byte[] serialBytes);
Expand Down Expand Up @@ -1195,6 +1195,36 @@ public void addExtension(int nid, String value, boolean isCritical)
public void addExtension(int nid, boolean value, boolean isCritical)
throws IllegalStateException, WolfSSLException {

addExtension(nid, value, -1, isCritical);
}

Comment thread
cconlon marked this conversation as resolved.
/**
* Add Basic Constraints extension with CA flag and path length
* constraint to a WOLFSSL_X509.
*
* This method allows setting the Basic Constraints extension with both the
* CA boolean and an optional path length constraint. The path length limits
* the number of intermediate CA certificates that may follow this
* certificate in a valid certification path.
*
* To set Basic Constraints without a path length constraint, use
* {@link #addExtension(int, boolean, boolean)} with
* {@code WolfSSL.NID_basic_constraints} instead.
*
* @param nid NID of extension to add. Must be:
* WolfSSL.NID_basic_constraints
* @param value Boolean value of CA flag (true for CA, false for end entity)
* @param pathLen Maximum number of intermediate CA certificates allowed
* below this CA. Must be &gt;= 0, or -1 to not set a path length
* constraint. Only meaningful when value is true.
* @param isCritical Boolean flag indicating if this extension is critical
*
* @throws IllegalStateException if WolfSSLCertificate has been freed
* @throws WolfSSLException if invalid arguments or on native JNI error.
*/
public void addExtension(int nid, boolean value, int pathLen,
boolean isCritical) throws IllegalStateException, WolfSSLException {

int ret = 0;

confirmObjectIsActive();
Expand All @@ -1203,20 +1233,38 @@ public void addExtension(int nid, boolean value, boolean isCritical)
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509Ptr,
() -> "entering addExtension(nid: " + nid + ", value: " +
value + ", isCritical: " + isCritical + ")");
value + ", pathLen: " + pathLen + ", isCritical: " +
isCritical + ")");
}

if (nid != WolfSSL.NID_basic_constraints) {
throw new WolfSSLException(
"Unsupported X509v3 extension NID: " + nid);
}

if (pathLen < -1) {
throw new WolfSSLException(
"Path length must be >= 0 or -1, got: " + pathLen);
}

Comment thread
cconlon marked this conversation as resolved.
if (!value && pathLen >= 0) {
throw new WolfSSLException(
"pathLen must not be set when isCA is FALSE (RFC 5280), " +
"got pathLen: " + pathLen);
}

synchronized (x509Lock) {
ret = X509_add_ext_via_set_object_boolean(
this.x509Ptr, nid, value, isCritical);
ret = X509_add_ext_via_set_object_boolean(this.x509Ptr, nid, value,
isCritical, pathLen);
}

if (ret != WolfSSL.SSL_SUCCESS) {
if (ret == WolfSSL.NOT_COMPILED_IN) {
throw new WolfSSLException(
"addExtension NOT_COMPILED_IN, pathLen " +
"support requires wolfSSL > 5.8.4 or " +
"PR 9940 patch (ret: " + ret + ")");
Comment thread
cconlon marked this conversation as resolved.
}
else if (ret != WolfSSL.SSL_SUCCESS) {
throw new WolfSSLException(
"Error setting extension into native WOLFSSL_X509 " +
"(ret: " + ret + ")");
Expand Down
55 changes: 55 additions & 0 deletions src/test/com/wolfssl/test/WolfSSLCertRequestTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ public static void setCertPaths() throws WolfSSLException {
cliEccKeyPem = WolfSSLTestCommon.getPath(cliEccKeyPem);
}

private boolean isNotCompiledIn(WolfSSLException e) {
String msg = e.getMessage();
if (msg == null) {
return false;
}
return msg.contains(
Integer.toString(WolfSSL.NOT_COMPILED_IN)) ||
msg.contains("NOT_COMPILED_IN");
}

/* Internal helper method, generate test SubjectName for cert generation */
private WolfSSLX509Name GenerateTestSubjectName() throws WolfSSLException {

Expand Down Expand Up @@ -185,6 +195,51 @@ public void testAddExtension()
req.addExtension(WolfSSL.NID_basic_constraints, true, true);
req.addExtension(WolfSSL.NID_basic_constraints, false, true);

/* Test boolean extension with pathLen */
try {
req.addExtension(WolfSSL.NID_basic_constraints, true, 0, true);
} catch (WolfSSLException e) {
if (!isNotCompiledIn(e)) {
throw e;
}
System.out.println("\t\t\t... skipped");
}
try {
req.addExtension(WolfSSL.NID_basic_constraints, true, 3, true);
} catch (WolfSSLException e) {
if (!isNotCompiledIn(e)) {
throw e;
}
System.out.println("\t\t\t... skipped");
}

/* Invalid pathLen (< -1) should throw WolfSSLException */
try {
req.addExtension(WolfSSL.NID_basic_constraints, true, -2, true);
System.out.println("\t\t\t... failed");
fail("Invalid pathLen did not throw exception");
} catch (WolfSSLException e) {
/* expected */
}
Comment thread
cconlon marked this conversation as resolved.

/* pathLen with isCA=false should throw (RFC 5280) */
try {
req.addExtension(WolfSSL.NID_basic_constraints, false, 0, true);
System.out.println("\t\t\t... failed");
fail("pathLen with isCA=false did not throw");
} catch (WolfSSLException e) {
/* expected */
}

/* Unsupported NID with pathLen should throw exception */
try {
req.addExtension(123456, true, 0, true);
System.out.println("\t\t\t... failed");
fail("Unsupported NID did not throw exception");
} catch (WolfSSLException e) {
/* expected */
}

/* Adding unsupported NID should throw exception */
try {
req.addExtension(123456, true, false);
Expand Down
Loading
Loading