@@ -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
0 commit comments