From 92b4826a7648b05678e9340e98af3453a9d064a2 Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Tue, 10 Jul 2018 12:09:46 -0400 Subject: [PATCH] Proper fix for compilation issue caused by deprecated API in Mojave (#30815) * Proper fix for compilation issue caused by deprecated API in macOS Mojave by using dlsym to call available API rather than suppressing deprecation warnings. Fixes: #30599 --- .../CMakeLists.txt | 3 -- .../pal_x509.c | 29 +++++++++++++++++-- .../pal_x509.h | 2 +- .../Internal/Cryptography/Pal.OSX/X509Pal.cs | 5 ++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/Native/Unix/System.Security.Cryptography.Native.Apple/CMakeLists.txt b/src/Native/Unix/System.Security.Cryptography.Native.Apple/CMakeLists.txt index 8feda36e523b..fcb96e1a4509 100644 --- a/src/Native/Unix/System.Security.Cryptography.Native.Apple/CMakeLists.txt +++ b/src/Native/Unix/System.Security.Cryptography.Native.Apple/CMakeLists.txt @@ -25,9 +25,6 @@ set(NATIVECRYPTO_SOURCES pal_x509chain.c ) -# Temporary workaround for dotnet/corefx issue #30599 -add_compile_options(-Wno-deprecated-declarations) - add_library(System.Security.Cryptography.Native.Apple SHARED ${NATIVECRYPTO_SOURCES} diff --git a/src/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.c b/src/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.c index f5d51eae583e..d15ed63d1c7e 100644 --- a/src/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.c +++ b/src/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.c @@ -3,9 +3,14 @@ // See the LICENSE file in the project root for more information. #include "pal_x509.h" +#include +#include static const int32_t kErrOutItemsNull = -3; static const int32_t kErrOutItemsEmpty = -2; +static pthread_once_t once = PTHREAD_ONCE_INIT; +static SecKeyRef (*secCertificateCopyKey)(SecCertificateRef); +static OSStatus (*secCertificateCopyPublicKey)(SecCertificateRef, SecKeyRef*); typedef const struct OpaqueSecCertificateRef * ConstSecCertificateRef; typedef const struct OpaqueSecIdentityRef * ConstSecIdentityRef; @@ -41,6 +46,12 @@ AppleCryptoNative_X509DemuxAndRetainHandle(CFTypeRef handle, SecCertificateRef* return 1; } +static void InitCertificateCopy() +{ + secCertificateCopyKey = (SecKeyRef (*)(SecCertificateRef))dlsym(RTLD_DEFAULT, "SecCertificateCopyKey"); + secCertificateCopyPublicKey = (OSStatus (*)(SecCertificateRef, SecKeyRef*))dlsym(RTLD_DEFAULT, "SecCertificateCopyPublicKey"); +} + int32_t AppleCryptoNative_X509GetPublicKey(SecCertificateRef cert, SecKeyRef* pPublicKeyOut, int32_t* pOSStatusOut) { @@ -50,9 +61,23 @@ AppleCryptoNative_X509GetPublicKey(SecCertificateRef cert, SecKeyRef* pPublicKey *pOSStatusOut = noErr; if (cert == NULL || pPublicKeyOut == NULL || pOSStatusOut == NULL) - return kErrorBadInput; + return kErrorUnknownState; - *pOSStatusOut = SecCertificateCopyPublicKey(cert, pPublicKeyOut); + pthread_once (&once, InitCertificateCopy); + // SecCertificateCopyPublicKey was deprecated in 10.14, so use SecCertificateCopyKey on the systems that have it (10.14+), + // and SecCertificateCopyPublicKey on the systems that don’t. + if (secCertificateCopyKey != NULL) + { + *pPublicKeyOut = (*secCertificateCopyKey)(cert); + } + else if (secCertificateCopyPublicKey != NULL) + { + *pOSStatusOut = (*secCertificateCopyPublicKey)(cert, pPublicKeyOut); + } + else + { + return kErrorBadInput; + } return (*pOSStatusOut == noErr); } diff --git a/src/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.h b/src/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.h index 544a940e50ea..1f468bd221c9 100644 --- a/src/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.h +++ b/src/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.h @@ -42,7 +42,7 @@ Returns 1 on success, 0 on failure, any other value on invalid state. Output: pPublicKeyOut: Receives a CFRetain()ed SecKeyRef for the public key -pOSStatusOut: Receives the result of SecCertificateCopyPublicKey +pOSStatusOut: Receives the result of SecCertificateCopyKey or SecCertificateCopyPublicKey, depending on the OS version. */ DLLEXPORT int32_t AppleCryptoNative_X509GetPublicKey(SecCertificateRef cert, SecKeyRef* pPublicKeyOut, int32_t* pOSStatusOut); diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.cs index 1056f0ccbbc9..a2fee97612bb 100644 --- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.cs +++ b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.cs @@ -33,6 +33,11 @@ public AsymmetricAlgorithm DecodePublicKey(Oid oid, byte[] encodedKeyValue, byte case Oids.RsaRsa: return new RSAImplementation.RSASecurityTransforms(key); case Oids.DsaDsa: + if (key.IsInvalid) + { + // SecCertificateCopyKey returns null for DSA, so fall back to manually building it. + return DecodeDsaPublicKey(encodedKeyValue, encodedParameters); + } return new DSAImplementation.DSASecurityTransforms(key); case Oids.Ecc: return new ECDsaImplementation.ECDsaSecurityTransforms(key);