internal static byte[] X509ExportPfx(IntPtr[] certHandles, SafePasswordHandle exportPassword)
        {
            SafeCreateHandle cfPassphrase    = s_emptyExportString;
            bool             releasePassword = false;

            try
            {
                if (!exportPassword.IsInvalid)
                {
                    exportPassword.DangerousAddRef(ref releasePassword);
                    IntPtr passwordHandle = exportPassword.DangerousGetHandle();

                    if (passwordHandle != IntPtr.Zero)
                    {
                        cfPassphrase = CoreFoundation.CFStringCreateWithCString(passwordHandle);
                    }
                }

                return(X509Export(X509ContentType.Pkcs12, cfPassphrase, certHandles));
            }
            finally
            {
                if (releasePassword)
                {
                    exportPassword.DangerousRelease();
                }

                if (cfPassphrase != s_emptyExportString)
                {
                    cfPassphrase.Dispose();
                }
            }
        }
Exemple #2
0
 private static partial int AppleCryptoNative_X509ImportCertificate(
     ref byte pbKeyBlob,
     int cbKeyBlob,
     X509ContentType contentType,
     SafeCreateHandle cfPfxPassphrase,
     out SafeSecCertificateHandle pCertOut,
     out SafeSecIdentityHandle pPrivateKeyOut);
Exemple #3
0
        private SafeCreateHandle GetCertsArray(IList <SafeHandle> safeHandles)
        {
            int idx = 0;

            try
            {
                int      handlesCount = safeHandles.Count;
                IntPtr[] ptrs         = new IntPtr[handlesCount];
                for (; idx < handlesCount; idx++)
                {
                    SafeHandle handle   = safeHandles[idx];
                    bool       addedRef = false;
                    handle.DangerousAddRef(ref addedRef);
                    ptrs[idx] = handle.DangerousGetHandle();
                }

                // Creating the array has the effect of calling CFRetain() on all of the pointers, so the native
                // resource is safe even if we DangerousRelease=>ReleaseHandle them.
                SafeCreateHandle certsArray = Interop.CoreFoundation.CFArrayCreate(ptrs, (UIntPtr)ptrs.Length);
                _extraHandles.Push(certsArray);
                return(certsArray);
            }
            finally
            {
                for (idx--; idx >= 0; idx--)
                {
                    safeHandles[idx].DangerousRelease();
                }
            }
        }
Exemple #4
0
        internal void OpenTrustHandle(
            ICertificatePal leafCert,
            X509Certificate2Collection extraStore,
            bool checkRevocation)
        {
            SafeCreateHandle policiesArray = PreparePoliciesArray(checkRevocation);
            SafeCreateHandle certsArray    = PrepareCertsArray(leafCert, extraStore);

            int osStatus;

            SafeX509ChainHandle chain;
            int ret = Interop.AppleCrypto.AppleCryptoNative_X509ChainCreate(
                certsArray,
                policiesArray,
                out chain,
                out osStatus);

            if (ret == 1)
            {
                _chainHandle = chain;
                return;
            }

            chain.Dispose();

            if (ret == 0)
            {
                throw Interop.AppleCrypto.CreateExceptionForOSStatus(osStatus);
            }

            Debug.Fail($"AppleCryptoNative_X509ChainCreate returned unexpected return value {ret}");
            throw new CryptographicException();
        }
Exemple #5
0
        private static SafeSecCertificateHandle X509ImportCertificate(
            ReadOnlySpan <byte> bytes,
            X509ContentType contentType,
            SafeCreateHandle?importPassword,
            out SafeSecIdentityHandle identityHandle)
        {
            SafeSecCertificateHandle certHandle;
            SafeCreateHandle         cfPassphrase = importPassword ?? s_emptyExportString;

            int osStatus = AppleCryptoNative_X509ImportCertificate(
                bytes,
                contentType,
                cfPassphrase,
                out certHandle,
                out identityHandle);

            if (osStatus == 0)
            {
                return(certHandle);
            }

            certHandle.Dispose();
            identityHandle.Dispose();

            throw CreateExceptionForOSStatus(osStatus);
        }
Exemple #6
0
        private SafeCreateHandle PreparePoliciesArray(bool checkRevocation)
        {
            IntPtr[] policies = new IntPtr[checkRevocation ? 2 : 1];

            SafeHandle defaultPolicy = Interop.AppleCrypto.X509ChainCreateDefaultPolicy();

            if (defaultPolicy.IsInvalid)
            {
                defaultPolicy.Dispose();
                throw new PlatformNotSupportedException(nameof(X509Chain));
            }

            _extraHandles.Push(defaultPolicy);
            policies[0] = defaultPolicy.DangerousGetHandle();

            if (checkRevocation)
            {
                SafeHandle revPolicy = Interop.AppleCrypto.X509ChainCreateRevocationPolicy();
                _extraHandles.Push(revPolicy);
                policies[1] = revPolicy.DangerousGetHandle();
            }

            SafeCreateHandle policiesArray =
                Interop.CoreFoundation.CFArrayCreate(policies, (UIntPtr)policies.Length);

            _extraHandles.Push(policiesArray);
            return(policiesArray);
        }
Exemple #7
0
        public Uri?GetProxy(Uri targetUri)
        {
            using (SafeCFDictionaryHandle systemProxySettings = CFNetworkCopySystemProxySettings())
                using (SafeCreateHandle cfurl = CFURLCreateWithString(targetUri.AbsoluteUri))
                    using (SafeCFArrayHandle proxies = CFNetworkCopyProxiesForURL(cfurl, systemProxySettings))
                    {
                        long proxyCount = CFArrayGetCount(proxies);
                        for (int i = 0; i < proxyCount; i++)
                        {
                            IntPtr proxyValue = CFArrayGetValueAtIndex(proxies, i);
                            using (SafeCFDictionaryHandle proxyDict = new SafeCFDictionaryHandle(proxyValue, false))
                            {
                                CFProxy proxy = new CFProxy(proxyDict);

                                if (proxy.ProxyType == CFProxy.kCFProxyTypeAutoConfigurationURL || proxy.ProxyType == CFProxy.kCFProxyTypeAutoConfigurationJavaScript)
                                {
                                    Uri?result = ExecuteProxyAutoConfiguration(cfurl, proxy);
                                    if (result != null)
                                    {
                                        return(result);
                                    }
                                }
                                else if (proxy.ProxyType == CFProxy.kCFProxyTypeHTTP || proxy.ProxyType == CFProxy.kCFProxyTypeHTTPS)
                                {
                                    return(GetProxyUri("http", proxy));
                                }
                            }
                        }
                    }

            return(null);
        }
        private static void RunLoopThreadStart()
        {
            Debug.Assert(s_runLoop == IntPtr.Zero);

            s_runLoop = Interop.RunLoop.CFRunLoopGetCurrent();
            Interop.RunLoop.CFRunLoopAddSource(
                s_runLoop,
                s_runLoopSource.DangerousGetHandle(),
                Interop.RunLoop.kCFRunLoopDefaultMode.DangerousGetHandle());

            s_runLoopStartedEvent.Set();
            Interop.RunLoop.CFRunLoopRun();

            Interop.RunLoop.CFRunLoopRemoveSource(
                s_runLoop,
                s_runLoopSource.DangerousGetHandle(),
                Interop.RunLoop.kCFRunLoopDefaultMode.DangerousGetHandle());

            s_runLoop = IntPtr.Zero;

            s_runLoopSource.Dispose();
            s_runLoopSource = null;

            s_dynamicStoreRef.Dispose();
            s_dynamicStoreRef = null;

            s_runLoopEndedEvent.Set();
        }
        private static byte[] X509Export(X509ContentType contentType, SafeCreateHandle cfPassphrase, IntPtr[] certHandles)
        {
            Debug.Assert(contentType == X509ContentType.Pkcs7 || contentType == X509ContentType.Pkcs12);

            using (SafeCreateHandle handlesArray = CoreFoundation.CFArrayCreate(certHandles, (UIntPtr)certHandles.Length))
            {
                SafeCFDataHandle exportData;
                int osStatus;

                int result = AppleCryptoNative_X509ExportData(
                    handlesArray,
                    contentType,
                    cfPassphrase,
                    out exportData,
                    out osStatus);

                using (exportData)
                {
                    if (result != 1)
                    {
                        if (result == 0)
                        {
                            throw CreateExceptionForOSStatus(osStatus);
                        }

                        Debug.Fail($"Unexpected result from AppleCryptoNative_X509ExportData: {result}");
                        throw new CryptographicException();
                    }

                    Debug.Assert(!exportData.IsInvalid, "Successful export yielded no data");
                    return(CoreFoundation.CFGetData(exportData));
                }
            }
        }
Exemple #10
0
        public static bool SslCheckHostnameMatch(SafeSslHandle handle, string hostName, DateTime notBefore)
        {
            int result;
            // The IdnMapping converts Unicode input into the IDNA punycode sequence.
            // It also does host case normalization.  The bypass logic would be something
            // like "all characters being within [a-z0-9.-]+"
            //
            // The SSL Policy (SecPolicyCreateSSL) has been verified as not inherently supporting
            // IDNA as of macOS 10.12.1 (Sierra).  If it supports low-level IDNA at a later date,
            // this code could be removed.
            //
            // It was verified as supporting case invariant match as of 10.12.1 (Sierra).
            string matchName = s_idnMapping.GetAscii(hostName);

            using (SafeCFDateHandle cfNotBefore = CoreFoundation.CFDateCreate(notBefore))
                using (SafeCreateHandle cfHostname = CoreFoundation.CFStringCreateWithCString(matchName))
                {
                    result = AppleCryptoNative_SslIsHostnameMatch(handle, cfHostname, cfNotBefore);
                }

            switch (result)
            {
            case 0:
                return(false);

            case 1:
                return(true);

            default:
                Debug.Fail($"AppleCryptoNative_SslIsHostnameMatch returned {result}");
                throw new SslException();
            }
        }
Exemple #11
0
 internal static SafeCreateHandle CFURLCreateWithString(string url)
 {
     Debug.Assert(url != null);
     using (SafeCreateHandle stringHandle = CFStringCreateWithCString(url))
     {
         return(CFURLCreateWithString(IntPtr.Zero, stringHandle, IntPtr.Zero));
     }
 }
Exemple #12
0
 private static extern SafeEventStreamHandle FSEventStreamCreate(
     IntPtr allocator,
     FSEventStreamCallback cb,
     IntPtr context,
     SafeCreateHandle pathsToWatch,
     FSEventStreamEventId sinceWhen,
     CFTimeInterval latency,
     FSEventStreamCreateFlags flags);
Exemple #13
0
 /// <summary>
 /// Creates a new EventStream to listen to events from the core OS (such as File System events).
 /// </summary>
 /// <param name="cb">A callback instance that will be called for every event batch.</param>
 /// <param name="pathsToWatch">A CFArray of the path(s) to watch for events.</param>
 /// <param name="sinceWhen">
 /// The start point to receive events from. This can be to retrieve historical events or only new events.
 /// To get historical events, pass in the corresponding ID of the event you want to start from.
 /// To get only new events, pass in kFSEventStreamEventIdSinceNow.
 /// </param>
 /// <param name="latency">Coalescing period to wait before sending events.</param>
 /// <param name="flags">Flags to say what kind of events should be sent through this stream.</param>
 /// <returns>On success, returns a valid SafeCreateHandle to an FSEventStream object; otherwise, returns an invalid SafeCreateHandle</returns>
 internal static SafeEventStreamHandle FSEventStreamCreate(
     FSEventStreamCallback cb,
     SafeCreateHandle pathsToWatch,
     FSEventStreamEventId sinceWhen,
     CFTimeInterval latency,
     FSEventStreamCreateFlags flags)
 {
     return(FSEventStreamCreate(IntPtr.Zero, cb, IntPtr.Zero, pathsToWatch, sinceWhen, latency, flags));
 }
        private void CreateStreamAndStartWatcher()
        {
            Debug.Assert(_eventStream.IsInvalid);
            Debug.Assert(_watcherRunLoop == IntPtr.Zero);
            Debug.Assert(_callback == null);

            // Make sure we only do this if there is a valid directory
            if (String.IsNullOrEmpty(_directory) == false)
            {
                _fullDirectory = System.IO.Path.GetFullPath(_directory);

                // Get the path to watch and verify we created the CFStringRef
                SafeCreateHandle path = Interop.CoreFoundation.CFStringCreateWithCString(_fullDirectory);
                if (path.IsInvalid)
                {
                    throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, true);
                }

                // Take the CFStringRef and put it into an array to pass to the EventStream
                SafeCreateHandle arrPaths = Interop.CoreFoundation.CFArrayCreate(new CFStringRef[1] {
                    path.DangerousGetHandle()
                }, 1);
                if (arrPaths.IsInvalid)
                {
                    path.Dispose();
                    throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, true);
                }

                // Create the callback for the EventStream
                _callback = new Interop.EventStream.FSEventStreamCallback(FileSystemEventCallback);

                // Make sure the OS file buffer(s) are fully flushed so we don't get events from cached I/O
                Interop.libc.sync();

                // Create the event stream for the path and tell the stream to watch for file system events.
                _eventStream = Interop.EventStream.FSEventStreamCreate(
                    _callback,
                    arrPaths,
                    Interop.EventStream.kFSEventStreamEventIdSinceNow,
                    0.0f,
                    EventStreamFlags);
                if (_eventStream.IsInvalid)
                {
                    arrPaths.Dispose();
                    path.Dispose();
                    throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, true);
                }

                // Create and start our watcher thread then wait for the thread to initialize and start
                // the RunLoop. We wait for that to prevent this function from returning before the RunLoop
                // has a chance to start so that any callers won't race with the background thread's initialization
                // and calling Stop, which would attempt to stop a RunLoop that hasn't started yet.
                _watcherThread = new Thread(new ThreadStart(WatchForFileSystemEventsThreadStart));
                _watcherThread.Start();
                _runLoopStartedEvent.WaitOne();
            }
        }
 private static extern int AppleCryptoNative_X509ImportCollection(
     byte[] pbKeyBlob,
     int cbKeyBlob,
     X509ContentType contentType,
     SafeCreateHandle cfPfxPassphrase,
     SafeKeychainHandle tmpKeychain,
     int exportable,
     out SafeCFArrayHandle pCollectionOut,
     out int pOSStatus);
Exemple #16
0
            internal void Start()
            {
                // Get the path to watch and verify we created the CFStringRef
                SafeCreateHandle path = Interop.CoreFoundation.CFStringCreateWithCString(_fullDirectory);

                if (path.IsInvalid)
                {
                    throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, true);
                }

                // Take the CFStringRef and put it into an array to pass to the EventStream
                SafeCreateHandle arrPaths = Interop.CoreFoundation.CFArrayCreate(new CFStringRef[1] {
                    path.DangerousGetHandle()
                }, 1);

                if (arrPaths.IsInvalid)
                {
                    path.Dispose();
                    throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, true);
                }

                // Create the callback for the EventStream if it wasn't previously created for this instance.
                if (_callback == null)
                {
                    _callback = new Interop.EventStream.FSEventStreamCallback(FileSystemEventCallback);
                }

                // Make sure the OS file buffer(s) are fully flushed so we don't get events from cached I/O
                Interop.Sys.Sync();

                // Create the event stream for the path and tell the stream to watch for file system events.
                _eventStream = Interop.EventStream.FSEventStreamCreate(
                    _callback,
                    arrPaths,
                    Interop.EventStream.kFSEventStreamEventIdSinceNow,
                    0.0f,
                    EventStreamFlags);
                if (_eventStream.IsInvalid)
                {
                    arrPaths.Dispose();
                    path.Dispose();
                    throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, true);
                }

                // Create and start our watcher thread then wait for the thread to initialize and start
                // the RunLoop. We wait for that to prevent this function from returning before the RunLoop
                // has a chance to start so that any callers won't race with the background thread's initialization
                // and calling Stop, which would attempt to stop a RunLoop that hasn't started yet.
                var runLoopStarted = new ManualResetEventSlim();

                new Thread(WatchForFileSystemEventsThreadStart)
                {
                    IsBackground = true
                }.Start(runLoopStarted);
                runLoopStarted.Wait();
            }
Exemple #17
0
        private SafeCreateHandle PrepareCertsArray(ICertificatePal cert, X509Certificate2Collection extraStore)
        {
            IntPtr[]     ptrs        = new IntPtr[1 + (extraStore?.Count ?? 0)];
            SafeHandle[] safeHandles = new SafeHandle[ptrs.Length];

            AppleCertificatePal applePal = (AppleCertificatePal)cert;

            safeHandles[0] = applePal.CertificateHandle;

            if (extraStore != null)
            {
                for (int i = 0; i < extraStore.Count; i++)
                {
                    AppleCertificatePal extraCertPal = (AppleCertificatePal)extraStore[i].Pal;

                    safeHandles[i + 1] = extraCertPal.CertificateHandle;
                }
            }

            int  idx      = 0;
            bool addedRef = false;

            try
            {
                for (idx = 0; idx < safeHandles.Length; idx++)
                {
                    SafeHandle handle = safeHandles[idx];
                    handle.DangerousAddRef(ref addedRef);
                    ptrs[idx] = handle.DangerousGetHandle();
                }
            }
            catch
            {
                // If any DangerousAddRef failed, idx will be on the one that failed, so we'll start off
                // by subtracing one.
                for (idx--; idx >= 0; idx--)
                {
                    safeHandles[idx].DangerousRelease();
                }

                throw;
            }

            // Creating the array has the effect of calling CFRetain() on all of the pointers, so the native
            // resource is safe even if we DangerousRelease=>ReleaseHandle them.
            SafeCreateHandle certsArray = Interop.CoreFoundation.CFArrayCreate(ptrs, (UIntPtr)ptrs.Length);

            _extraHandles.Push(certsArray);

            for (idx = 0; idx < safeHandles.Length; idx++)
            {
                safeHandles[idx].DangerousRelease();
            }

            return(certsArray);
        }
 private static extern int AppleCryptoNative_X509ImportCertificate(
     byte[] pbKeyBlob,
     int cbKeyBlob,
     X509ContentType contentType,
     SafeCreateHandle cfPfxPassphrase,
     SafeKeychainHandle tmpKeychain,
     int exportable,
     out SafeSecCertificateHandle pCertOut,
     out SafeSecIdentityHandle pPrivateKeyOut,
     out int pOSStatus);
Exemple #19
0
        internal static unsafe void SslCtxSetAlpnProtos(SafeSslHandle ctx, List <SslApplicationProtocol> protocols)
        {
            SafeCreateHandle cfProtocolsRefs = null;

            SafeCreateHandle[] cfProtocolsArrayRef = null;
            try
            {
                if (protocols.Count == 1 && protocols[0] == SslApplicationProtocol.Http2)
                {
                    cfProtocolsRefs = s_cfAlpnHttp211Protocols;
                }
                else if (protocols.Count == 1 && protocols[0] == SslApplicationProtocol.Http11)
                {
                    cfProtocolsRefs = s_cfAlpnHttp11Protocols;
                }
                else if (protocols.Count == 2 && protocols[0] == SslApplicationProtocol.Http2 && protocols[1] == SslApplicationProtocol.Http11)
                {
                    cfProtocolsRefs = s_cfAlpnHttp211Protocols;
                }
                else
                {
                    // we did not match common case. This is more expensive path allocating Core Foundation objects.
                    cfProtocolsArrayRef = new SafeCreateHandle[protocols.Count];
                    IntPtr[] protocolsPtr = new System.IntPtr[protocols.Count];

                    for (int i = 0; i < protocols.Count; i++)
                    {
                        cfProtocolsArrayRef[i] = CoreFoundation.CFStringCreateWithCString(protocols[i].ToString());
                        protocolsPtr[i]        = cfProtocolsArrayRef[i].DangerousGetHandle();
                    }

                    cfProtocolsRefs = CoreFoundation.CFArrayCreate(protocolsPtr, (UIntPtr)protocols.Count);
                }

                int osStatus;
                int result = SSLSetALPNProtocols(ctx, cfProtocolsRefs, out osStatus);
                if (result != 1)
                {
                    throw CreateExceptionForOSStatus(osStatus);
                }
            }
            finally
            {
                if (cfProtocolsArrayRef != null)
                {
                    for (int i = 0; i < cfProtocolsArrayRef.Length; i++)
                    {
                        cfProtocolsArrayRef[i]?.Dispose();
                    }

                    cfProtocolsRefs?.Dispose();
                }
            }
        }
Exemple #20
0
        internal static void SslSetCertificate(SafeSslHandle sslHandle, IntPtr[] certChainPtrs)
        {
            using (SafeCreateHandle cfCertRefs = CoreFoundation.CFArrayCreate(certChainPtrs, (UIntPtr)certChainPtrs.Length))
            {
                int osStatus = AppleCryptoNative_SslSetCertificate(sslHandle, cfCertRefs);

                if (osStatus != 0)
                {
                    throw CreateExceptionForOSStatus(osStatus);
                }
            }
        }
        internal static SafeSecCertificateHandle X509ImportCertificate(
            byte[] bytes,
            X509ContentType contentType,
            SafeCreateHandle importPassword,
            SafeKeychainHandle keychain,
            bool exportable,
            out SafeSecIdentityHandle identityHandle)
        {
            SafeSecCertificateHandle certHandle;
            int osStatus;

            SafeCreateHandle cfPassphrase = importPassword ?? s_nullExportString;

            int ret = AppleCryptoNative_X509ImportCertificate(
                bytes,
                bytes.Length,
                contentType,
                cfPassphrase,
                keychain,
                exportable ? 1 : 0,
                out certHandle,
                out identityHandle,
                out osStatus);

            SafeTemporaryKeychainHandle.TrackItem(certHandle);
            SafeTemporaryKeychainHandle.TrackItem(identityHandle);

            if (ret == 1)
            {
                return(certHandle);
            }

            certHandle.Dispose();
            identityHandle.Dispose();

            const int SeeOSStatus         = 0;
            const int ImportReturnedEmpty = -2;
            const int ImportReturnedNull  = -3;

            switch (ret)
            {
            case SeeOSStatus:
                throw CreateExceptionForOSStatus(osStatus);

            case ImportReturnedNull:
            case ImportReturnedEmpty:
                throw new CryptographicException();

            default:
                Debug.Fail($"Unexpected return value {ret}");
                throw new CryptographicException();
            }
        }
Exemple #22
0
        internal static unsafe void SslSetCertificateAuthorities(SafeSslHandle sslHandle, Span <IntPtr> certificates, bool replaceExisting)
        {
            using (SafeCreateHandle cfCertRefs = CoreFoundation.CFArrayCreate(certificates))
            {
                int osStatus = SslSetCertificateAuthorities(sslHandle, cfCertRefs, replaceExisting ? 1 : 0);

                if (osStatus != 0)
                {
                    throw CreateExceptionForOSStatus(osStatus);
                }
            }
        }
Exemple #23
0
        internal static SafeCFArrayHandle X509ImportCollection(
            ReadOnlySpan <byte> bytes,
            X509ContentType contentType,
            SafePasswordHandle importPassword)
        {
            SafeCreateHandle  cfPassphrase    = s_emptyExportString;
            bool              releasePassword = false;
            SafeCFArrayHandle collectionHandle;
            int osStatus;

            try
            {
                if (!importPassword.IsInvalid)
                {
                    importPassword.DangerousAddRef(ref releasePassword);
                    IntPtr passwordHandle = importPassword.DangerousGetHandle();

                    if (passwordHandle != IntPtr.Zero)
                    {
                        cfPassphrase = CoreFoundation.CFStringCreateWithCString(passwordHandle);
                    }
                }

                osStatus = AppleCryptoNative_X509ImportCollection(
                    ref MemoryMarshal.GetReference(bytes),
                    bytes.Length,
                    contentType,
                    cfPassphrase,
                    out collectionHandle);

                if (osStatus == 0)
                {
                    return(collectionHandle);
                }
            }
            finally
            {
                if (releasePassword)
                {
                    importPassword.DangerousRelease();
                }

                if (cfPassphrase != s_emptyExportString)
                {
                    cfPassphrase.Dispose();
                }
            }

            collectionHandle.Dispose();
            throw CreateExceptionForOSStatus(osStatus);
        }
        internal static byte[] SecKeyExport(
            SafeSecKeyRefHandle key,
            bool exportPrivate,
            string password)
        {
            SafeCreateHandle exportPassword = exportPrivate
                ? CoreFoundation.CFStringCreateWithCString(password)
                : s_nullExportString;

            int ret;
            SafeCFDataHandle cfData;
            int osStatus;

            try
            {
                ret = AppleCryptoNative_SecKeyExport(
                    key,
                    exportPrivate ? 1 : 0,
                    exportPassword,
                    out cfData,
                    out osStatus);
            }
            finally
            {
                if (exportPassword != s_nullExportString)
                {
                    exportPassword.Dispose();
                }
            }

            byte[] exportedData;

            using (cfData)
            {
                if (ret == 0)
                {
                    throw CreateExceptionForOSStatus(osStatus);
                }

                if (ret != 1)
                {
                    Debug.Fail($"AppleCryptoNative_SecKeyExport returned {ret}");
                    throw new CryptographicException();
                }

                exportedData = CoreFoundation.CFGetData(cfData);
            }

            return(exportedData);
        }
Exemple #25
0
        public Uri?ExecuteProxyAutoConfiguration(SafeCreateHandle cfurl, CFProxy proxy)
        {
            Uri?         result  = null;
            CFRunLoopRef runLoop = CFRunLoopGetCurrent();

            // Callback that will be called after executing the configuration script
            CFProxyAutoConfigurationResultCallback cb = (IntPtr client, IntPtr proxyListHandle, IntPtr error) =>
            {
                if (proxyListHandle != IntPtr.Zero)
                {
                    using (var proxyList = new SafeCFArrayHandle(proxyListHandle, false))
                    {
                        long proxyCount = CFArrayGetCount(proxyList);
                        for (int i = 0; i < proxyCount; i++)
                        {
                            IntPtr proxyValue = CFArrayGetValueAtIndex(proxyList, i);
                            using (SafeCFDictionaryHandle proxyDict = new SafeCFDictionaryHandle(proxyValue, false))
                            {
                                CFProxy proxy = new CFProxy(proxyDict);
                                if (proxy.ProxyType == CFProxy.kCFProxyTypeHTTP || proxy.ProxyType == CFProxy.kCFProxyTypeHTTPS)
                                {
                                    result = GetProxyUri("http", proxy);
                                    break;
                                }
                            }
                        }
                    }
                }
                CFRunLoopStop(runLoop);
            };

            CFStreamClientContext clientContext = default;
            CFRunLoopSourceRef    loopSource    =
                proxy.ProxyType == CFProxy.kCFProxyTypeAutoConfigurationURL ?
                CFNetworkExecuteProxyAutoConfigurationURL(proxy.AutoConfigurationURL, cfurl, cb, ref clientContext) :
                CFNetworkExecuteProxyAutoConfigurationScript(proxy.AutoConfigurationJavaScript, cfurl, cb, ref clientContext);

            using (var mode = CFStringCreateWithCString(typeof(MacProxy).FullName !))
            {
                IntPtr modeHandle = mode.DangerousGetHandle();
                CFRunLoopAddSource(runLoop, loopSource, modeHandle);
                CFRunLoopRunInMode(modeHandle, double.MaxValue, 0);
                CFRunLoopSourceInvalidate(loopSource);
            }

            GC.KeepAlive(cb);

            return(result);
        }
Exemple #26
0
 private static int AppleCryptoNative_X509ImportCertificate(
     ReadOnlySpan <byte> keyBlob,
     X509ContentType contentType,
     SafeCreateHandle cfPfxPassphrase,
     out SafeSecCertificateHandle pCertOut,
     out SafeSecIdentityHandle pPrivateKeyOut)
 {
     return(AppleCryptoNative_X509ImportCertificate(
                ref MemoryMarshal.GetReference(keyBlob),
                keyBlob.Length,
                contentType,
                cfPfxPassphrase,
                out pCertOut,
                out pPrivateKeyOut));
 }
        internal static SafeCFDataHandle SecKeyExportData(
            SafeSecKeyRefHandle?key,
            bool exportPrivate,
            ReadOnlySpan <char> password)
        {
            SafeCreateHandle exportPassword = exportPrivate
                ? CoreFoundation.CFStringCreateFromSpan(password)
                : s_nullExportString;

            int ret;
            SafeCFDataHandle cfData;
            int osStatus;

            try
            {
                ret = AppleCryptoNative_SecKeyExport(
                    key,
                    exportPrivate ? 1 : 0,
                    exportPassword,
                    out cfData,
                    out osStatus);
            }
            finally
            {
                if (exportPassword != s_nullExportString)
                {
                    exportPassword.Dispose();
                }
            }

            if (ret == 1)
            {
                return(cfData);
            }

            cfData.Dispose();

            if (ret == 0)
            {
                throw CreateExceptionForOSStatus(osStatus);
            }

            Debug.Fail($"AppleCryptoNative_SecKeyExport returned {ret}");
            throw new CryptographicException();
        }
        internal static SafeSecCertificateHandle X509ImportCertificate(
            byte[] bytes,
            X509ContentType contentType,
            SafePasswordHandle importPassword,
            SafeKeychainHandle keychain,
            bool exportable,
            out SafeSecIdentityHandle identityHandle)
        {
            SafeCreateHandle cfPassphrase    = null;
            bool             releasePassword = false;

            try
            {
                if (!importPassword.IsInvalid)
                {
                    importPassword.DangerousAddRef(ref releasePassword);
                    cfPassphrase = CoreFoundation.CFStringCreateFromSpan(importPassword.DangerousGetSpan());
                }

                return(X509ImportCertificate(
                           bytes,
                           contentType,
                           cfPassphrase,
                           keychain,
                           exportable,
                           out identityHandle));
            }
            finally
            {
                if (releasePassword)
                {
                    importPassword.DangerousRelease();
                }

                cfPassphrase?.Dispose();
            }
        }
Exemple #29
0
 private static extern int AppleCryptoNative_SslIsHostnameMatch(
     SafeSslHandle handle,
     SafeCreateHandle cfHostname,
     SafeCFDateHandle cfValidTime);
Exemple #30
0
 internal static extern int SSLSetALPNProtocols(SafeSslHandle ctx, SafeCreateHandle cfProtocolsRefs, out int osStatus);