Skip to content

Commit ec9b6cf

Browse files
committed
Add test cases
1 parent 452652b commit ec9b6cf

6 files changed

Lines changed: 330 additions & 96 deletions

File tree

.github/workflows/cmake.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ jobs:
7676
-DWOLFSSL_EXTRA_PQC_HYBRIDS:BOOL=yes -DWOLFSSL_TLS_NO_MLKEM_STANDALONE:BOOL=no \
7777
..
7878
cmake --build .
79-
ctest -j $(nproc)
79+
ctest -j $(nproc) --output-on-failure
8080
cmake --install .
8181
8282
# clean up

src/internal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13751,7 +13751,7 @@ static void CopyDateToASN1_TIME(const byte* srcDate, int srcDateLen,
1375113751
{
1375213752
if (srcDateLen >= 2) {
1375313753
/* Clamp the date length to the maximum allowed size.
13754-
* This needs to match the size of WOLFSSL_ASN1_TIME minus the
13754+
* This needs to match the size of WOLFSSL_ASN1_TIME minus the
1375513755
* the type and length fields. */
1375613756
const int maxSz = CTC_DATE_SIZE - 2;
1375713757
const int copySz = (int)min(srcDate[1], maxSz);

tests/api/test_ossl_x509.c

Lines changed: 125 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -663,124 +663,160 @@ int test_wolfSSL_X509_set_name(void)
663663
return EXPECT_RESULT();
664664
}
665665

666-
int test_wolfSSL_X509_set_notAfter(void)
666+
int test_wolfSSL_X509_set_notAfterBefore(void)
667667
{
668668
EXPECT_DECLS;
669669
#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) \
670670
&& !defined(NO_ASN_TIME) && !defined(USER_TIME) && \
671671
!defined(TIME_OVERRIDES) && !defined(NO_CERTS) && \
672-
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) &&\
673-
!defined(TIME_T_NOT_64BIT) && !defined(NO_64BIT) && !defined(NO_BIO)
674-
/* Generalized time will overflow time_t if not long */
672+
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && !defined(NO_BIO)
675673
X509* x = NULL;
676674
BIO* bio = NULL;
677-
ASN1_TIME *asn_time = NULL;
678-
ASN1_TIME *time_check = NULL;
679-
const int year = 365*24*60*60;
680-
const int day = 24*60*60;
681-
const int hour = 60*60;
675+
ASN1_TIME* asn_time = NULL;
676+
ASN1_TIME* time_check = NULL;
677+
WOLFSSL_ASN1_TIME crafted_time;
678+
WOLFSSL_ASN1_TIME* retrieved = NULL;
679+
const byte* raw = NULL;
680+
const int year = 365 * 24 * 60 * 60;
681+
const int day = 24 * 60 * 60;
682+
const int hour = 60 * 60;
682683
const int mini = 60;
683-
int offset_day;
684684
unsigned char buf[25];
685-
time_t t;
685+
const unsigned char valid_utc[] = "250101120000Z";
686+
const int valid_utc_len = 13;
687+
int i;
686688

687-
/*
688-
* Setup asn_time. APACHE HTTPD uses time(NULL)
689-
*/
690-
t = (time_t)107 * year + 31 * day + 34 * hour + 30 * mini + 7 * day;
691-
offset_day = 7;
692-
/*
693-
* Free these.
694-
*/
695-
asn_time = wolfSSL_ASN1_TIME_adj(NULL, t, offset_day, 0);
696-
ExpectNotNull(asn_time);
697689
ExpectNotNull(x = X509_new());
698690
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
699-
/*
700-
* Tests
701-
*/
691+
692+
/* --- notBefore: set, get, validate, print --- */
693+
{
694+
time_t t = (time_t)49 * year + 125 * day + 20 * hour +
695+
30 * mini + 7 * day;
696+
asn_time = wolfSSL_ASN1_TIME_adj(NULL, t, 7, 0);
697+
}
698+
ExpectNotNull(asn_time);
699+
ExpectIntEQ(ASN1_TIME_check(asn_time), WOLFSSL_SUCCESS);
700+
ExpectTrue(wolfSSL_X509_set_notBefore(x, asn_time));
701+
ExpectNotNull(time_check = X509_get_notBefore(x));
702+
ExpectIntEQ(ASN1_TIME_check(time_check), WOLFSSL_SUCCESS);
703+
ExpectIntEQ(ASN1_TIME_print(bio, time_check), 1);
704+
ExpectIntEQ(BIO_read(bio, buf, sizeof(buf)), 24);
705+
ExpectIntEQ(XMEMCMP(buf, "May 8 20:30:00 2019 GMT", sizeof(buf) - 1), 0);
706+
707+
/* wolfSSL_X509_notBefore returns [type][length][data...] */
708+
ExpectNotNull(raw = wolfSSL_X509_notBefore(x));
709+
ExpectIntEQ(raw[0], time_check->type);
710+
ExpectIntEQ(raw[1], time_check->length);
711+
ExpectIntEQ(XMEMCMP(&raw[2], time_check->data, time_check->length), 0);
712+
713+
XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL);
714+
asn_time = NULL;
715+
716+
/* --- notAfter: set, get, validate, print (needs 64-bit time_t) --- */
717+
#if !defined(TIME_T_NOT_64BIT) && !defined(NO_64BIT)
718+
{
719+
time_t t = (time_t)107 * year + 31 * day + 34 * hour +
720+
30 * mini + 7 * day;
721+
asn_time = wolfSSL_ASN1_TIME_adj(NULL, t, 7, 0);
722+
}
723+
ExpectNotNull(asn_time);
702724
ExpectTrue(wolfSSL_X509_set_notAfter(x, asn_time));
703-
/* time_check is simply (ANS1_TIME*)x->notAfter */
704725
ExpectNotNull(time_check = X509_get_notAfter(x));
705-
/* ANS1_TIME_check validates by checking if argument can be parsed */
706726
ExpectIntEQ(ASN1_TIME_check(time_check), WOLFSSL_SUCCESS);
707-
/* Convert to human readable format and compare to intended date */
708727
ExpectIntEQ(ASN1_TIME_print(bio, time_check), 1);
709728
ExpectIntEQ(BIO_read(bio, buf, sizeof(buf)), 24);
710729
ExpectIntEQ(XMEMCMP(buf, "Jan 20 10:30:00 2077 GMT", sizeof(buf) - 1), 0);
711730

712-
ExpectFalse(wolfSSL_X509_set_notAfter(NULL, NULL));
713-
ExpectFalse(wolfSSL_X509_set_notAfter(x, NULL));
714-
ExpectFalse(wolfSSL_X509_set_notAfter(NULL, asn_time));
731+
/* wolfSSL_X509_notAfter returns [type][length][data...] */
732+
ExpectNotNull(raw = wolfSSL_X509_notAfter(x));
733+
ExpectIntEQ(raw[0], time_check->type);
734+
ExpectIntEQ(raw[1], time_check->length);
735+
ExpectIntEQ(XMEMCMP(&raw[2], time_check->data, time_check->length), 0);
715736

716-
/*
717-
* Cleanup
718-
*/
719737
XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL);
720-
X509_free(x);
721-
BIO_free(bio);
738+
asn_time = NULL;
722739
#endif
723-
return EXPECT_RESULT();
724-
}
725740

726-
int test_wolfSSL_X509_set_notBefore(void)
727-
{
728-
EXPECT_DECLS;
729-
#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) \
730-
&& !defined(NO_ASN_TIME) && !defined(USER_TIME) && \
731-
!defined(TIME_OVERRIDES) && !defined(NO_CERTS) && \
732-
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && !defined(NO_BIO)
733-
X509* x = NULL;
734-
BIO* bio = NULL;
735-
ASN1_TIME *asn_time = NULL;
736-
ASN1_TIME *time_check = NULL;
737-
const int year = 365*24*60*60;
738-
const int day = 24*60*60;
739-
const int hour = 60*60;
740-
const int mini = 60;
741-
int offset_day;
742-
unsigned char buf[25];
743-
time_t t;
744-
745-
/*
746-
* Setup asn_time. APACHE HTTPD uses time(NULL)
747-
*/
748-
t = (time_t)49 * year + 125 * day + 20 * hour + 30 * mini + 7 * day;
749-
offset_day = 7;
750-
751-
/*
752-
* Free these.
753-
*/
754-
asn_time = wolfSSL_ASN1_TIME_adj(NULL, t, offset_day, 0);
755-
ExpectNotNull(asn_time);
756-
ExpectNotNull(x = X509_new());
757-
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
758-
ExpectIntEQ(ASN1_TIME_check(asn_time), WOLFSSL_SUCCESS);
759-
760-
/*
761-
* Main Tests
762-
*/
763-
ExpectTrue(wolfSSL_X509_set_notBefore(x, asn_time));
764-
/* time_check == (ANS1_TIME*)x->notBefore */
765-
ExpectNotNull(time_check = X509_get_notBefore(x));
766-
/* ANS1_TIME_check validates by checking if argument can be parsed */
767-
ExpectIntEQ(ASN1_TIME_check(time_check), WOLFSSL_SUCCESS);
768-
/* Convert to human readable format and compare to intended date */
769-
ExpectIntEQ(ASN1_TIME_print(bio, time_check), 1);
770-
ExpectIntEQ(BIO_read(bio, buf, sizeof(buf)), 24);
771-
ExpectIntEQ(XMEMCMP(buf, "May 8 20:30:00 2019 GMT", sizeof(buf) - 1), 0);
741+
/* --- NULL parameter tests --- */
742+
XMEMSET(&crafted_time, 0, sizeof(crafted_time));
743+
crafted_time.type = ASN_UTC_TIME;
744+
crafted_time.length = valid_utc_len;
745+
XMEMCPY(crafted_time.data, valid_utc, valid_utc_len);
772746

747+
ExpectFalse(wolfSSL_X509_set_notAfter(NULL, NULL));
748+
ExpectFalse(wolfSSL_X509_set_notAfter(x, NULL));
749+
ExpectFalse(wolfSSL_X509_set_notAfter(NULL, &crafted_time));
773750
ExpectFalse(wolfSSL_X509_set_notBefore(NULL, NULL));
774751
ExpectFalse(wolfSSL_X509_set_notBefore(x, NULL));
775-
ExpectFalse(wolfSSL_X509_set_notBefore(NULL, asn_time));
776-
752+
ExpectFalse(wolfSSL_X509_set_notBefore(NULL, &crafted_time));
777753
ExpectNull(X509_get_notBefore(NULL));
778754
ExpectNull(X509_get_notAfter(NULL));
755+
ExpectNull(wolfSSL_X509_notBefore(NULL));
756+
ExpectNull(wolfSSL_X509_notAfter(NULL));
757+
758+
/* --- Malicious length > CTC_DATE_SIZE via set_notAfter ---
759+
* The function blindly propagates t->length into the x509 struct.
760+
* A fixed implementation would reject this or clamp to CTC_DATE_SIZE. */
761+
/* --- Length > CTC_DATE_SIZE is rejected by the bounds check --- */
762+
XMEMSET(&crafted_time, 0, sizeof(crafted_time));
763+
crafted_time.type = ASN_UTC_TIME;
764+
crafted_time.length = 255;
765+
XMEMCPY(crafted_time.data, valid_utc, valid_utc_len);
766+
ExpectIntEQ(wolfSSL_X509_set_notAfter(x, &crafted_time),
767+
WOLFSSL_FAILURE);
768+
769+
crafted_time.length = 128;
770+
ExpectIntEQ(wolfSSL_X509_set_notBefore(x, &crafted_time),
771+
WOLFSSL_FAILURE);
772+
773+
/* --- Negative length is rejected --- */
774+
crafted_time.length = -1;
775+
ExpectIntEQ(wolfSSL_X509_set_notAfter(x, &crafted_time),
776+
WOLFSSL_FAILURE);
777+
778+
/* --- Fixed-size copy leaks sentinel bytes beyond valid length ---
779+
* Even when t->length is correct (13 for UTCTime), XMEMCPY copies
780+
* a full CTC_DATE_SIZE (32) bytes from the source. */
781+
XMEMSET(&crafted_time, 0, sizeof(crafted_time));
782+
crafted_time.type = ASN_UTC_TIME;
783+
crafted_time.length = valid_utc_len;
784+
XMEMCPY(crafted_time.data, valid_utc, valid_utc_len);
785+
for (i = valid_utc_len; i < CTC_DATE_SIZE; i++) {
786+
crafted_time.data[i] = 0xDE;
787+
}
788+
789+
ExpectIntEQ(wolfSSL_X509_set_notAfter(x, &crafted_time), WOLFSSL_SUCCESS);
790+
ExpectNotNull(retrieved = X509_get_notAfter(x));
791+
ExpectBufEQ(retrieved->data, valid_utc, valid_utc_len);
792+
for (i = valid_utc_len; i < CTC_DATE_SIZE; i++) {
793+
ExpectIntEQ(retrieved->data[i], 0xDE);
794+
}
795+
796+
/* --- Boundary: length CTC_DATE_SIZE - 2 (accepted) --- */
797+
XMEMSET(&crafted_time, 0, sizeof(crafted_time));
798+
crafted_time.type = ASN_GENERALIZED_TIME;
799+
crafted_time.length = CTC_DATE_SIZE - 2;
800+
XMEMSET(crafted_time.data, 'A', CTC_DATE_SIZE - 2);
801+
802+
ExpectIntEQ(wolfSSL_X509_set_notAfter(x, &crafted_time),
803+
WOLFSSL_SUCCESS);
804+
ExpectNotNull(retrieved = X509_get_notAfter(x));
805+
ExpectIntEQ(retrieved->length, CTC_DATE_SIZE - 2);
806+
807+
/* wolfSSL_X509_notAfter must also succeed at this boundary */
808+
ExpectNotNull(raw = wolfSSL_X509_notAfter(x));
809+
810+
/* --- Boundary: length CTC_DATE_SIZE - 1 (rejected) --- */
811+
crafted_time.length = CTC_DATE_SIZE - 1;
812+
ExpectIntEQ(wolfSSL_X509_set_notAfter(x, &crafted_time),
813+
WOLFSSL_FAILURE);
814+
815+
/* --- Boundary: length CTC_DATE_SIZE (rejected) --- */
816+
crafted_time.length = CTC_DATE_SIZE;
817+
ExpectIntEQ(wolfSSL_X509_set_notAfter(x, &crafted_time),
818+
WOLFSSL_FAILURE);
779819

780-
/*
781-
* Cleanup
782-
*/
783-
XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL);
784820
X509_free(x);
785821
BIO_free(bio);
786822
#endif

tests/api/test_ossl_x509.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ int test_wolfSSL_X509_check_email(void);
3737
int test_wolfSSL_X509(void);
3838
int test_wolfSSL_X509_get0_tbs_sigalg(void);
3939
int test_wolfSSL_X509_set_name(void);
40-
int test_wolfSSL_X509_set_notAfter(void);
41-
int test_wolfSSL_X509_set_notBefore(void);
40+
int test_wolfSSL_X509_set_notAfterBefore(void);
4241
int test_wolfSSL_X509_set_version(void);
4342
int test_wolfSSL_X509_get_serialNumber(void);
4443
int test_wolfSSL_get_tbs(void);
@@ -69,8 +68,7 @@ int test_wolfSSL_X509_cmp(void);
6968
TEST_DECL_GROUP("ossl_x509", test_wolfSSL_X509), \
7069
TEST_DECL_GROUP("ossl_x509", test_wolfSSL_X509_get0_tbs_sigalg), \
7170
TEST_DECL_GROUP("ossl_x509", test_wolfSSL_X509_set_name), \
72-
TEST_DECL_GROUP("ossl_x509", test_wolfSSL_X509_set_notAfter), \
73-
TEST_DECL_GROUP("ossl_x509", test_wolfSSL_X509_set_notBefore), \
71+
TEST_DECL_GROUP("ossl_x509", test_wolfSSL_X509_set_notAfterBefore), \
7472
TEST_DECL_GROUP("ossl_x509", test_wolfSSL_X509_set_version), \
7573
TEST_DECL_GROUP("ossl_x509", test_wolfSSL_X509_get_serialNumber), \
7674
TEST_DECL_GROUP("ossl_x509", test_wolfSSL_get_tbs), \

0 commit comments

Comments
 (0)