// See the LICENSE file in the project root for more information.
#include "pal_x509.h"
+#include <dlfcn.h>
+#include <pthread.h>
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;
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)
{
*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);
}
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);