diff options
author | Jeremy Barton <jbarton@microsoft.com> | 2021-07-08 21:07:03 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-08 21:07:03 +0300 |
commit | fcc773770c33079fa4148f405fe8aa4cfae6d297 (patch) | |
tree | 9d69dee147adec1cf9d049f63d965e3f432d93a0 /src | |
parent | 75960326d918ee482065406b9e77394825552a5c (diff) |
[release/5.0] Add name of corrupted certificate to CryptographicException on Mac (#54613)
* Add name of corrupted certificate to CryptographicException on Mac
When trying to create a CertificateData out of raw X509 byte array it might throw if the data is corrupted. The existing exception message does not provide any information which might help the user identify the corrupted certificate and fix it.
This change, makes a native call to SecCertificateCopySubjectSummary which will provide a human readable summary of the certificate, and will generate an exception message using this string.
* Only call the diagnostic method on failure
Diffstat (limited to 'src')
5 files changed, 71 insertions, 1 deletions
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 87eb51a3512..29e3ffbb72f 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 @@ -70,6 +70,11 @@ internal static partial class Interop 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); internal static X509ContentType X509GetContentType(ReadOnlySpan<byte> data) @@ -305,6 +310,31 @@ internal static partial class Interop } } + 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 SafeSecCertificateHandle X509GetCertFromIdentity(SafeSecIdentityHandle identity) { SafeSecCertificateHandle cert; 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 649b5ed2e56..1074808a911 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 @@ -257,6 +257,18 @@ int32_t AppleCryptoNative_X509CopyPrivateKeyFromIdentity(SecIdentityRef identity return SecIdentityCopyPrivateKey(identity, pPrivateKeyOut); } +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); +} + #if !defined(TARGET_IOS) && !defined(TARGET_TVOS) static int32_t ReadX509(uint8_t* pbData, int32_t cbData, 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 f9d2f4c322a..0f44980d300 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 @@ -73,6 +73,11 @@ pPrivateKeyOut: Receives a SecKeyRef for the private key associated with the ide */ PALEXPORT int32_t AppleCryptoNative_X509CopyPrivateKeyFromIdentity(SecIdentityRef identity, SecKeyRef* pPrivateKeyOut); +/* +Extract a string that contains a human-readable summary of the contents of the certificate +*/ +PALEXPORT int32_t AppleCryptoNative_X509GetSubjectSummary(SecCertificateRef cert, CFStringRef* ppSummaryOut); + #if !defined(TARGET_IOS) && !defined(TARGET_TVOS) /* Read cbData bytes of data from pbData and interpret it to a collection of certificates (or identities). 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 c54cd0e6f00..bf384787bc9 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 @@ -667,7 +667,27 @@ namespace Internal.Cryptography.Pal return; Debug.Assert(!_certHandle.IsInvalid); - _certData = new CertificateData(Interop.AppleCrypto.X509GetRawData(_certHandle)); + + try + { + _certData = new CertificateData(Interop.AppleCrypto.X509GetRawData(_certHandle)); + } + catch (CryptographicException e) + { + string? subjectSummary = Interop.AppleCrypto.X509GetSubjectSummary(_certHandle); + + 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 40eb18f054f..6b81b7966ea 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx @@ -298,6 +298,9 @@ <data name="Cryptography_X509_NoOrMismatchedPemKey" xml:space="preserve"> <value>The key contents do not contain a PEM, the content is malformed, or the key does not match the certificate.</value> </data> + <data name="Cryptography_X509_CertificateCorrupted" xml:space="preserve"> + <value>Certificate '{0}' is corrupted.</value> + </data> <data name="InvalidOperation_EnumNotStarted" xml:space="preserve"> <value>Enumeration has not started. Call MoveNext.</value> </data> |