diff --git a/native/com_wolfssl_WolfSSLCertificate.c b/native/com_wolfssl_WolfSSLCertificate.c index c48cf38..f9b609b 100644 --- a/native/com_wolfssl_WolfSSLCertificate.c +++ b/native/com_wolfssl_WolfSSLCertificate.c @@ -469,13 +469,18 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1notBefore WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; WOLFSSL_ASN1_TIME* asnBefore = NULL; int ret = WOLFSSL_SUCCESS; - time_t notBeforeTime = (time_t)(long)notBefore; + time_t notBeforeTime = (time_t)notBefore; (void)jcl; if (jenv == NULL || x509 == NULL) { return WOLFSSL_FAILURE; } + /* Reject values the platform time_t cannot represent */ + if ((jlong)notBeforeTime != notBefore) { + return WOLFSSL_FAILURE; + } + /* set time_t value into WOLFSSL_ASN1_TIME struct, no adjustment */ asnBefore = wolfSSL_ASN1_TIME_adj(NULL, notBeforeTime, 0, 0); if (asnBefore == NULL) { @@ -509,13 +514,18 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1notAfter WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; WOLFSSL_ASN1_TIME* asnAfter = NULL; int ret = WOLFSSL_SUCCESS; - time_t notAfterTime = (time_t)(long)notAfter; + time_t notAfterTime = (time_t)notAfter; (void)jcl; if (jenv == NULL || x509 == NULL) { return WOLFSSL_FAILURE; } + /* Reject values the platform time_t cannot represent */ + if ((jlong)notAfterTime != notAfter) { + return WOLFSSL_FAILURE; + } + /* set time_t value into WOLFSSL_ASN1_TIME struct, no adjustment */ asnAfter = wolfSSL_ASN1_TIME_adj(NULL, notAfterTime, 0, 0); if (asnAfter == NULL) { diff --git a/src/test/com/wolfssl/test/WolfSSLCertificateTest.java b/src/test/com/wolfssl/test/WolfSSLCertificateTest.java index 0ea9e1d..628dac3 100644 --- a/src/test/com/wolfssl/test/WolfSSLCertificateTest.java +++ b/src/test/com/wolfssl/test/WolfSSLCertificateTest.java @@ -928,6 +928,66 @@ public class WolfSSLCertificateTest { } } + /* A validity date after the 2038 32-bit time_t rollover must round-trip + * through the notBefore and notAfter setters. */ + @Test + public void test_setNotBeforeNotAfterPost2038RoundTrips() + throws WolfSSLException, WolfSSLJNIException, IOException { + + Assume.assumeTrue(WolfSSL.FileSystemEnabled()); + + Date notBefore = Date.from(Instant.parse("2039-01-01T00:00:00Z")); + Date notAfter = Date.from(Instant.parse("2040-01-01T00:00:00Z")); + Date representable = Date.from(Instant.parse("2020-01-01T00:00:00Z")); + + WolfSSLCertificate x509 = new WolfSSLCertificate(); + WolfSSLX509Name name = null; + byte[] der; + + try { + /* A representable date must set cleanly. Let a failure here + * propagate, since it is a real regression not a time_t limit. */ + x509.setNotBefore(representable); + + /* A 32-bit time_t cannot hold a post-2038 date, so the setter + * rejects it there. Skip rather than fail on those platforms. */ + try { + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + } catch (WolfSSLException e) { + Assume.assumeNoException( + "post-2038 validity dates require 64-bit time_t", e); + } + + x509.setSerialNumber(BigInteger.valueOf(1125)); + + name = new WolfSSLX509Name(); + name.setCommonName("post 2038 test"); + x509.setSubjectName(name); + + x509.setPublicKey(cliKeyPubDer, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1); + x509.signCert(cliKeyDer, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1, "SHA256"); + der = x509.getDer(); + } finally { + if (name != null) { + name.free(); + } + x509.free(); + } + + WolfSSLCertificate cert = new WolfSSLCertificate(der); + try { + assertEquals("post-2038 notBefore must round-trip", + notBefore, cert.notBefore()); + assertEquals("post-2038 notAfter must round-trip", + notAfter, cert.notAfter()); + } finally { + cert.free(); + } + } + /* Generate a self-signed cert with the given CN and an optional single * SubjectAltName entry, return its DER encoding. */ private byte[] genIpTestCertDer(String cn, String sanValue, int sanType)