@@ -875,3 +875,97 @@ int test_x509_CertFromX509_akid_overflow(void)
875875#endif
876876 return EXPECT_RESULT ();
877877}
878+
879+ /* Test that ReqCertFromX509() rejects a CSR with an oversized
880+ * SubjectKeyIdentifier (> CTC_MAX_SKID_SIZE = 32 bytes). Before the fix
881+ * this would cause a heap buffer overflow into cert->skid[32]. */
882+ int test_x509_ReqCertFromX509_skid_overflow (void )
883+ {
884+ EXPECT_DECLS ;
885+ #if defined(WOLFSSL_CERT_REQ ) && defined(WOLFSSL_CERT_GEN ) && \
886+ defined(WOLFSSL_CERT_EXT ) && !defined(NO_BIO ) && \
887+ (defined(OPENSSL_EXTRA ) || defined(OPENSSL_ALL )) && \
888+ defined(HAVE_ECC )
889+
890+ /* Minimal DER-encoded CSR (PKCS#10) containing a SubjectKeyIdentifier
891+ * extension with a 64-byte value — double the 32-byte CTC_MAX_SKID_SIZE
892+ * destination buffer.
893+ *
894+ * Structure:
895+ * SEQUENCE {
896+ * CertificationRequestInfo SEQUENCE {
897+ * version INTEGER 0
898+ * subject: CN=Test
899+ * subjectPKInfo: EC P-256 (generator point)
900+ * attributes [0] {
901+ * SEQUENCE {
902+ * OID 1.2.840.113549.1.9.14 (extensionRequest)
903+ * SET { SEQUENCE { -- Extensions
904+ * SEQUENCE { -- Extension
905+ * OID 2.5.29.14 (subjectKeyIdentifier)
906+ * OCTET STRING { OCTET STRING (64 bytes of 0x41) }
907+ * }
908+ * }}
909+ * }
910+ * }
911+ * }
912+ * signatureAlgorithm: ecdsa-with-SHA256
913+ * signatureValue: dummy
914+ * }
915+ */
916+ static const unsigned char crafted_csr_der [] = {
917+ 0x30 , 0x81 , 0xE7 , 0x30 , 0x81 , 0xCD , 0x02 , 0x01 ,
918+ 0x00 , 0x30 , 0x0F , 0x31 , 0x0D , 0x30 , 0x0B , 0x06 ,
919+ 0x03 , 0x55 , 0x04 , 0x03 , 0x0C , 0x04 , 0x54 , 0x65 ,
920+ 0x73 , 0x74 , 0x30 , 0x59 , 0x30 , 0x13 , 0x06 , 0x07 ,
921+ 0x2A , 0x86 , 0x48 , 0xCE , 0x3D , 0x02 , 0x01 , 0x06 ,
922+ 0x08 , 0x2A , 0x86 , 0x48 , 0xCE , 0x3D , 0x03 , 0x01 ,
923+ 0x07 , 0x03 , 0x42 , 0x00 , 0x04 , 0x6B , 0x17 , 0xD1 ,
924+ 0xF2 , 0xE1 , 0x2C , 0x42 , 0x47 , 0xF8 , 0xBC , 0xE6 ,
925+ 0xE5 , 0x63 , 0xA4 , 0x40 , 0xF2 , 0x77 , 0x03 , 0x7D ,
926+ 0x81 , 0x2D , 0xEB , 0x33 , 0xA0 , 0xF4 , 0xA1 , 0x39 ,
927+ 0x45 , 0xD8 , 0x98 , 0xC2 , 0x96 , 0x4F , 0xE3 , 0x42 ,
928+ 0xE2 , 0xFE , 0x1A , 0x7F , 0x9B , 0x8E , 0xE7 , 0xEB ,
929+ 0x4A , 0x7C , 0x0F , 0x9E , 0x16 , 0x2B , 0xCE , 0x33 ,
930+ 0x57 , 0x6B , 0x31 , 0x5E , 0xCE , 0xCB , 0xB6 , 0x40 ,
931+ 0x68 , 0x37 , 0xBF , 0x51 , 0xF5 , 0xA0 , 0x5C , 0x30 ,
932+ 0x5A , 0x06 , 0x09 , 0x2A , 0x86 , 0x48 , 0x86 , 0xF7 ,
933+ 0x0D , 0x01 , 0x09 , 0x0E , 0x31 , 0x4D , 0x30 , 0x4B ,
934+ 0x30 , 0x49 , 0x06 , 0x03 , 0x55 , 0x1D , 0x0E , 0x04 ,
935+ 0x42 , 0x04 , 0x40 ,
936+ /* 64 bytes of 0x41 — oversized SKID value */
937+ 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
938+ 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
939+ 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
940+ 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
941+ 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
942+ 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
943+ 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
944+ 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 , 0x41 ,
945+ /* end of SKID payload */
946+ 0x30 , 0x0A , 0x06 , 0x08 , 0x2A , 0x86 , 0x48 , 0xCE ,
947+ 0x3D , 0x04 , 0x03 , 0x02 , 0x03 , 0x09 , 0x00 , 0x30 ,
948+ 0x06 , 0x02 , 0x01 , 0x01 , 0x02 , 0x01 , 0x01
949+ };
950+
951+ WOLFSSL_X509 * req = NULL ;
952+ WOLFSSL_BIO * bio = NULL ;
953+
954+ /* Step 1: Parse the crafted CSR — this should succeed (the parser
955+ * dynamically allocates subjKeyId to the parsed size). */
956+ req = wolfSSL_X509_REQ_d2i (NULL , crafted_csr_der ,
957+ (int )sizeof (crafted_csr_der ));
958+ ExpectNotNull (req );
959+
960+ /* Step 2: Attempt to re-encode. Before the fix, this triggered a
961+ * heap buffer overflow in ReqCertFromX509() writing 64 bytes into
962+ * cert->skid[32]. With the fix, it must return failure. */
963+ bio = wolfSSL_BIO_new (wolfSSL_BIO_s_mem ());
964+ ExpectNotNull (bio );
965+ ExpectIntNE (wolfSSL_i2d_X509_REQ_bio (bio , req ), WOLFSSL_SUCCESS );
966+
967+ wolfSSL_BIO_free (bio );
968+ wolfSSL_X509_free (req );
969+ #endif
970+ return EXPECT_RESULT ();
971+ }
0 commit comments