@@ -1025,6 +1025,105 @@ TEST(NodeCrypto, X509FormattingPreservesUnrelatedErrors) {
10251025 ERR_clear_error ();
10261026}
10271027
1028+ TEST (NodeCrypto, X509IssuerChecksPreserveUnrelatedErrors) {
1029+ ncrypto::ClearErrorOnReturn clear_errors;
1030+ auto ctx = EVPKeyCtxPointer::NewFromAlgorithm (KeyAlgorithm::RSA );
1031+ ASSERT_TRUE (ctx);
1032+ ASSERT_TRUE (ctx.initForKeygen ());
1033+ ASSERT_TRUE (ctx.setRsaKeygenBits (2048 ));
1034+ EVP_PKEY * raw = nullptr ;
1035+ ASSERT_EQ (EVP_PKEY_keygen (ctx.get (), &raw), 1 );
1036+ EVPKeyPointer key (raw);
1037+
1038+ ncrypto::X509Pointer cert (X509_new ());
1039+ ASSERT_TRUE (cert);
1040+ ASSERT_EQ (X509_set_version (cert.get (), 2 ), 1 );
1041+ ASSERT_EQ (ASN1_INTEGER_set (X509_get_serialNumber (cert.get ()), 1 ), 1 );
1042+ ASSERT_EQ (
1043+ ASN1_TIME_set_string (X509_getm_notBefore (cert.get ()), " 20260101000000Z" ),
1044+ 1 );
1045+ ASSERT_EQ (
1046+ ASN1_TIME_set_string (X509_getm_notAfter (cert.get ()), " 20270101000000Z" ),
1047+ 1 );
1048+ X509NamePointer name (X509_NAME_new ());
1049+ ASSERT_TRUE (name);
1050+ ASSERT_EQ (X509_NAME_add_entry_by_txt (
1051+ name.get (),
1052+ " CN" ,
1053+ MBSTRING_ASC ,
1054+ reinterpret_cast <const unsigned char *>(" issuer" ),
1055+ -1 ,
1056+ -1 ,
1057+ 0 ),
1058+ 1 );
1059+ ASSERT_EQ (X509_set_subject_name (cert.get (), name.get ()), 1 );
1060+ ASSERT_EQ (X509_set_issuer_name (cert.get (), name.get ()), 1 );
1061+ ASSERT_EQ (X509_set_pubkey (cert.get (), key.get ()), 1 );
1062+ ASSERT_GT (X509_sign (cert.get (), key.get (), EVP_sha256 ()), 0 );
1063+
1064+ X509NamePointer mismatch_name (X509_NAME_dup (name.get ()));
1065+ ASSERT_TRUE (mismatch_name);
1066+ ASSERT_EQ (X509_NAME_add_entry_by_txt (
1067+ mismatch_name.get (),
1068+ " OU" ,
1069+ MBSTRING_ASC ,
1070+ reinterpret_cast <const unsigned char *>(" other" ),
1071+ -1 ,
1072+ -1 ,
1073+ 0 ),
1074+ 1 );
1075+
1076+ ncrypto::DeleteFnPtr<ASN1_OCTET_STRING , ASN1_OCTET_STRING_free> invalid_value (
1077+ ASN1_OCTET_STRING_new ());
1078+ ASSERT_TRUE (invalid_value);
1079+ const unsigned char truncated_sequence[] = {0x30 };
1080+ ASSERT_EQ (
1081+ ASN1_OCTET_STRING_set (
1082+ invalid_value.get (), truncated_sequence, sizeof (truncated_sequence)),
1083+ 1 );
1084+ X509ExtensionPointer invalid_constraints (X509_EXTENSION_create_by_NID (
1085+ nullptr , NID_basic_constraints, 0 , invalid_value.get ()));
1086+ ASSERT_TRUE (invalid_constraints);
1087+
1088+ for (const bool seed_error : {true , false }) {
1089+ // Reparse each issuer so extension-cache failures are exercised each time.
1090+ auto matching_issuer = cert.view ().clone ();
1091+ auto mismatch = cert.view ().clone ();
1092+ auto malformed = cert.view ().clone ();
1093+ ASSERT_TRUE (matching_issuer);
1094+ ASSERT_TRUE (mismatch);
1095+ ASSERT_TRUE (malformed);
1096+ ASSERT_EQ (X509_set_subject_name (mismatch.get (), mismatch_name.get ()), 1 );
1097+ ASSERT_EQ (X509_add_ext (malformed.get (), invalid_constraints.get (), -1 ), 1 );
1098+
1099+ const auto check = [seed_error](ncrypto::X509View subject,
1100+ ncrypto::X509View issuer,
1101+ bool issued) {
1102+ ERR_clear_error ();
1103+ if (seed_error) {
1104+ #if NCRYPTO_USE_OPENSSL_PROVIDER
1105+ ERR_raise (ERR_LIB_USER , 1 );
1106+ #elif NCRYPTO_USE_BORINGSSL
1107+ ERR_put_error (ERR_LIB_USER , 0 , 1 , __FILE__, __LINE__);
1108+ #else
1109+ #error "Unsupported crypto backend"
1110+ #endif
1111+ }
1112+ const auto expected = ERR_peek_error ();
1113+ if (seed_error) ASSERT_NE (expected, 0UL );
1114+ EXPECT_EQ (subject.isIssuedBy (issuer), issued);
1115+ EXPECT_EQ (ERR_get_error (), expected);
1116+ EXPECT_EQ (ERR_get_error (), 0UL );
1117+ };
1118+
1119+ check (cert.view (), matching_issuer.view (), true );
1120+ check (cert.view (), mismatch.view (), false );
1121+ check (cert.view (), malformed.view (), false );
1122+ check ({}, matching_issuer.view (), false );
1123+ check (cert.view (), {}, false );
1124+ }
1125+ }
1126+
10281127TEST (NodeCrypto, X509KeyVisitorsHandleMissingPublicKey) {
10291128 ncrypto::X509Pointer cert (X509_new ());
10301129 ASSERT_TRUE (cert);
0 commit comments