diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509.cs
index d50ca014c4e3a..6d39eabdaa180 100644
--- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509.cs
+++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509.cs
@@ -20,6 +20,11 @@ private static extern int AppleCryptoNative_X509GetRawData(
out SafeCFDataHandle cfDataOut,
out int pOSStatus);
+ [DllImport(Libraries.AppleCryptoNative)]
+ private static extern int AppleCryptoNative_X509GetSubjectSummary(
+ SafeSecCertificateHandle cert,
+ out SafeCFStringHandle cfSubjectSummaryOut);
+
[DllImport(Libraries.AppleCryptoNative)]
private static extern int AppleCryptoNative_X509GetPublicKey(SafeSecCertificateHandle cert, out SafeSecKeyRefHandle publicKey, out int pOSStatus);
@@ -69,6 +74,31 @@ internal static byte[] X509GetRawData(SafeSecCertificateHandle cert)
throw new CryptographicException();
}
+ internal static string? X509GetSubjectSummary(SafeSecCertificateHandle cert)
+ {
+ SafeCFStringHandle subjectSummary;
+
+ int ret = AppleCryptoNative_X509GetSubjectSummary(
+ cert,
+ out subjectSummary);
+
+ using (subjectSummary)
+ {
+ if (ret == 1)
+ {
+ return CoreFoundation.CFStringToString(subjectSummary);
+ }
+ }
+
+ if (ret == 0)
+ {
+ return null;
+ }
+
+ Debug.Fail($"Unexpected return value {ret}");
+ throw new CryptographicException();
+ }
+
internal static SafeSecKeyRefHandle X509GetPrivateKeyFromIdentity(SafeSecIdentityHandle identity)
{
SafeSecKeyRefHandle key;
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/entrypoints.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/entrypoints.c
index ff4df6f41fcb2..1833d4a2161ac 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/entrypoints.c
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/entrypoints.c
@@ -106,6 +106,7 @@ static const Entry s_cryptoAppleNative[] =
DllImportEntry(AppleCryptoNative_GetOSStatusForChainStatus)
DllImportEntry(AppleCryptoNative_X509ChainSetTrustAnchorCertificates)
DllImportEntry(AppleCryptoNative_Pbkdf2)
+ DllImportEntry(AppleCryptoNative_X509GetSubjectSummary)
};
EXTERN_C const void* CryptoAppleResolveDllImport(const char* name);
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.c
index 7d3e61f4b5d57..0b6d1f889bc69 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.c
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.c
@@ -230,3 +230,15 @@ int32_t AppleCryptoNative_X509GetRawData(SecCertificateRef cert, CFDataRef* ppDa
*pOSStatus = *ppDataOut == NULL ? errSecParam : noErr;
return (*pOSStatus == noErr);
}
+
+int32_t AppleCryptoNative_X509GetSubjectSummary(SecCertificateRef cert, CFStringRef* ppSummaryOut)
+{
+ if (ppSummaryOut != NULL)
+ *ppSummaryOut = NULL;
+
+ if (cert == NULL || ppSummaryOut == NULL)
+ return kErrorBadInput;
+
+ *ppSummaryOut = SecCertificateCopySubjectSummary(cert);
+ return (*ppSummaryOut != NULL);
+}
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.h
index 28124de10c98d..a0bc58044c3eb 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.h
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.h
@@ -72,3 +72,13 @@ ppDataOut: Receives a CFDataRef with the exported blob
pOSStatus: Receives the result of SecItemExport
*/
PALEXPORT int32_t AppleCryptoNative_X509GetRawData(SecCertificateRef cert, CFDataRef* ppDataOut, int32_t* pOSStatus);
+
+/*
+Extract a string that contains a human-readable summary of the contents of the certificate
+
+Returns 1 on success, 0 on failure, any other value indicates invalid state.
+
+Output:
+ppSummaryOut: Receives a CFDataRef with the exported blob
+*/
+PALEXPORT int32_t AppleCryptoNative_X509GetSubjectSummary(SecCertificateRef cert, CFStringRef* ppSummaryOut);
diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.cs
index cb949b8a93f7a..07959c3e77b5a 100644
--- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.cs
+++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/AppleCertificatePal.cs
@@ -399,7 +399,26 @@ private void EnsureCertData()
return;
Debug.Assert(!_certHandle.IsInvalid);
- _certData = new CertificateData(Interop.AppleCrypto.X509GetRawData(_certHandle));
+ string? subjectSummary = Interop.AppleCrypto.X509GetSubjectSummary(_certHandle);
+
+ try
+ {
+ _certData = new CertificateData(Interop.AppleCrypto.X509GetRawData(_certHandle));
+ }
+ catch (CryptographicException e)
+ {
+ if (subjectSummary is null)
+ {
+ throw;
+ }
+
+ string message = SR.Format(
+ SR.Cryptography_X509_CertificateCorrupted,
+ subjectSummary);
+
+ throw new CryptographicException(message, e);
+ }
+
_readCertData = true;
}
}
diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx
index a5c33a43b40b8..322e2bab91d0c 100644
--- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx
+++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx
@@ -331,6 +331,9 @@
The key contents do not contain a PEM, the content is malformed, or the key does not match the certificate.
+
+ Certificate '{0}' is corrupted.
+
Enumeration has not started. Call MoveNext.