示例#1
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);
        }
示例#2
0
 private static partial int AppleCryptoNative_X509ImportCertificate(
     ref byte pbKeyBlob,
     int cbKeyBlob,
     X509ContentType contentType,
     SafeCreateHandle cfPfxPassphrase,
     out SafeSecCertificateHandle pCertOut,
     out SafeSecIdentityHandle pPrivateKeyOut);
示例#3
0
        internal static SafeSecCertificateHandle X509ImportCertificate(
            ReadOnlySpan <byte> bytes,
            X509ContentType contentType,
            SafePasswordHandle importPassword,
            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,
                           out identityHandle));
            }
            finally
            {
                if (releasePassword)
                {
                    importPassword.DangerousRelease();
                }

                cfPassphrase?.Dispose();
            }
        }
示例#4
0
        internal AppleCertificatePal(SafeSecIdentityHandle identityHandle)
        {
            Debug.Assert(!identityHandle.IsInvalid);

            _identityHandle = identityHandle;
            _certHandle     = Interop.AppleCrypto.X509GetCertFromIdentity(identityHandle);
        }
 void SetCertificate(SafeSecIdentityHandle identify, IList <SafeSecCertificateHandle> certificates)
 {
     using (var array = Bundle(identify, certificates)) {
         var result = SSLSetCertificate(Handle, array.Handle);
         CheckStatusAndThrow(result);
     }
 }
示例#6
0
        private ICertificatePal CopyWithPrivateKey(SecKeyPair keyPair)
        {
            if (keyPair.PrivateKey == null)
            {
                // Both Windows and Linux/OpenSSL are unaware if they bound a public or private key.
                // Here, we do know.  So throw if we can't do what they asked.
                throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
            }

            SafeKeychainHandle keychain = Interop.AppleCrypto.SecKeychainItemCopyKeychain(keyPair.PrivateKey);

            if (keychain.IsInvalid)
            {
                keychain = Interop.AppleCrypto.CreateTemporaryKeychain();
            }

            using (keychain)
            {
                SafeSecIdentityHandle identityHandle = Interop.AppleCrypto.X509CopyWithPrivateKey(
                    _certHandle,
                    keyPair.PrivateKey,
                    keychain);

                AppleCertificatePal newPal = new AppleCertificatePal(identityHandle);
                newPal.HoldPrivateKey();
                return(newPal);
            }
        }
示例#7
0
        public void Dispose()
        {
            _certHandle?.Dispose();
            _identityHandle?.Dispose();

            _certHandle     = null;
            _identityHandle = null;
        }
 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);
示例#9
0
        public void Dispose()
        {
            _certHandle?.Dispose();
            _identityHandle?.Dispose();
            _privateKeyHolder?.Dispose();

            _certHandle       = null;
            _identityHandle   = null;
            _privateKeyHolder = null;
        }
        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();
            }
        }
示例#11
0
        internal AppleCertificatePal MoveToKeychain(SafeKeychainHandle keychain, SafeSecKeyRefHandle privateKey)
        {
            SafeSecIdentityHandle identity = Interop.AppleCrypto.X509MoveToKeychain(
                _certHandle,
                keychain,
                privateKey);

            if (identity != null)
            {
                return(new AppleCertificatePal(identity));
            }

            return(null);
        }
示例#12
0
        public static SafeSecCertificateHandle GetCertificate(SafeSecIdentityHandle identity)
        {
            if (identity == null || identity.IsInvalid)
            {
                throw new ArgumentNullException(nameof(identity));
            }
            var result = SecIdentityCopyCertificate(identity.DangerousGetHandle(), out var cert);

            if (result != SecStatusCode.Success)
            {
                throw new InvalidOperationException(result.ToString());
            }
            return(new SafeSecCertificateHandle(cert, true));
        }
        public override void StartHandshake()
        {
            Debug("StartHandshake: {0}", IsServer);

            if (Interlocked.CompareExchange(ref handshakeStarted, 1, 1) != 0)
            {
                throw new InvalidOperationException();
            }

            InitializeConnection();

            /*
             * SecureTransport is bugged OS X 10.5.8+ - renegotiation after
             * calling SetCertificate() will not work.
             *
             * We also cannot change options after the handshake has started,
             * so if you want to request a client certificate, it will happen
             * both during the initial handshake and during renegotiation.
             *
             * You may check 'SslStream.IsAuthenticated' (which will be false
             * during the initial handshake) from within your
             * 'LocalCertificateSelectionCallback' and return null to have the
             * callback invoked again during renegotiation.
             *
             * However, the first time your selection callback returns a client
             * certificate, that certificate will be used for the rest of the
             * session.
             */

            SetSessionOption(SslSessionOption.BreakOnCertRequested, true);
            SetSessionOption(SslSessionOption.BreakOnClientAuth, true);
            SetSessionOption(SslSessionOption.BreakOnServerAuth, true);

            if (IsServer)
            {
                SafeSecCertificateHandle[] intermediateCerts;
                serverIdentity = AppleCertificateHelper.GetIdentity(LocalServerCertificate, out intermediateCerts);
                if (serverIdentity.IsInvalid)
                {
                    throw new SSA.AuthenticationException("Unable to get server certificate from keychain.");
                }

                SetCertificate(serverIdentity, intermediateCerts);
                for (int i = 0; i < intermediateCerts.Length; i++)
                {
                    intermediateCerts [i].Dispose();
                }
            }
        }
示例#14
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));
 }
        void ClientCertificateRequested()
        {
            EvaluateTrust();
            var acceptableIssuers = CopyDistinguishedNames();

            localClientCertificate = SelectClientCertificate(acceptableIssuers);
            if (localClientCertificate == null)
            {
                return;
            }
            clientIdentity = AppleCertificateHelper.GetIdentity(localClientCertificate);
            if (clientIdentity.IsInvalid)
            {
                throw new TlsException(AlertDescription.CertificateUnknown);
            }
            SetCertificate(clientIdentity, new SafeSecCertificateHandle [0]);
        }
示例#16
0
        internal static SafeSecKeyRefHandle X509GetPrivateKeyFromIdentity(SafeSecIdentityHandle identity)
        {
            SafeSecKeyRefHandle key;
            int osStatus = AppleCryptoNative_X509CopyPrivateKeyFromIdentity(identity, out key);

            if (osStatus != 0)
            {
                key.Dispose();
                throw CreateExceptionForOSStatus(osStatus);
            }

            if (key.IsInvalid)
            {
                key.Dispose();
                throw new CryptographicException(SR.Cryptography_OpenInvalidHandle);
            }

            return(key);
        }
        static SafeSecIdentityHandle FindIdentity(Predicate <SafeSecCertificateHandle> filter)
        {
            Initialize();

            /*
             * Unfortunately, SecItemCopyMatching() does not allow any search
             * filters when looking up an identity.
             *
             * The following lookup will return all identities from the keychain -
             * we then need need to find the right one.
             */
            using (var query = CFMutableDictionary.Create()) {
                query.SetValue(SecClassKey, SecClassIdentity);
                query.SetValue(CFBoolean.True.Handle, ReturnRef);
                query.SetValue(MatchLimitAll, MatchLimit);

                var status = SecItemCopyMatching(query.Handle, out var ptr);
                if (status != SecStatusCode.Success || ptr == IntPtr.Zero)
                {
                    return(null);
                }

                using (var array = new CFArray(ptr, false)) {
                    for (int i = 0; i < array.Count; i++)
                    {
                        var item = array[i];
                        if (!MonoCertificatePal.IsSecIdentity(item))
                        {
                            throw new InvalidOperationException();
                        }
                        using (var identity = new SafeSecIdentityHandle(item))
                            using (var certificate = MonoCertificatePal.GetCertificate(identity)) {
                                if (filter(certificate))
                                {
                                    return(new SafeSecIdentityHandle(item));
                                }
                            }
                    }
                }
            }

            return(null);
        }
示例#18
0
        internal static SafeSecCertificateHandle X509GetCertFromIdentity(SafeSecIdentityHandle identity)
        {
            SafeSecCertificateHandle cert;
            int osStatus = AppleCryptoNative_X509CopyCertFromIdentity(identity, out cert);

            if (osStatus != 0)
            {
                cert.Dispose();
                throw CreateExceptionForOSStatus(osStatus);
            }

            if (cert.IsInvalid)
            {
                cert.Dispose();
                throw new CryptographicException(SR.Cryptography_OpenInvalidHandle);
            }

            return(cert);
        }
示例#19
0
        internal static bool X509DemuxAndRetainHandle(
            IntPtr handle,
            out SafeSecCertificateHandle certHandle,
            out SafeSecIdentityHandle identityHandle)
        {
            int result = AppleCryptoNative_X509DemuxAndRetainHandle(handle, out certHandle, out identityHandle);

            switch (result)
            {
            case 1:
                return(true);

            case 0:
                return(false);

            default:
                Debug.Fail($"AppleCryptoNative_X509DemuxAndRetainHandle returned {result}");
                throw new CryptographicException();
            }
        }
        CFArray Bundle(SafeSecIdentityHandle identity, IList <SafeSecCertificateHandle> certificates)
        {
            if (identity == null || identity.IsInvalid)
            {
                throw new ArgumentNullException(nameof(identity));
            }
            if (certificates == null)
            {
                throw new ArgumentNullException(nameof(certificates));
            }

            var ptrs = new IntPtr [certificates.Count + 1];

            ptrs [0] = identity.DangerousGetHandle();
            for (int i = 0; i < certificates.Count; i++)
            {
                ptrs [i + 1] = certificates [i].DangerousGetHandle();
            }
            return(CFArray.CreateArray(ptrs));
        }
 protected override void Dispose(bool disposing)
 {
     try {
         if (disposed)
         {
             return;
         }
         if (disposing)
         {
             disposed = true;
             if (serverIdentity != null)
             {
                 serverIdentity.Dispose();
                 serverIdentity = null;
             }
             if (clientIdentity != null)
             {
                 clientIdentity.Dispose();
                 clientIdentity = null;
             }
             if (remoteCertificate != null)
             {
                 remoteCertificate.Dispose();
                 remoteCertificate = null;
             }
         }
     } finally {
         disposed = true;
         if (context != IntPtr.Zero)
         {
             CFObject.CFRelease(context);
             context = IntPtr.Zero;
         }
         base.Dispose(disposing);
     }
 }
示例#22
0
        private ICertificatePal CopyWithPrivateKey(SecKeyPair keyPair)
        {
            if (keyPair.PrivateKey == null)
            {
                // Both Windows and Linux/OpenSSL are unaware if they bound a public or private key.
                // Here, we do know.  So throw if we can't do what they asked.
                throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
            }

            SafeKeychainHandle keychain = Interop.AppleCrypto.SecKeychainItemCopyKeychain(keyPair.PrivateKey);

            // If we're using a key already in a keychain don't add the certificate to that keychain here,
            // do it in the temporary add/remove in the shim.
            SafeKeychainHandle cloneKeychain = SafeTemporaryKeychainHandle.InvalidHandle;

            if (keychain.IsInvalid)
            {
                keychain      = Interop.AppleCrypto.CreateTemporaryKeychain();
                cloneKeychain = keychain;
            }

            // Because SecIdentityRef only has private constructors we need to have the cert and the key
            // in the same keychain.  That almost certainly means we're going to need to add this cert to a
            // keychain, and when a cert that isn't part of a keychain gets added to a keychain then the
            // interior pointer of "what keychain did I come from?" used by SecKeychainItemCopyKeychain gets
            // set. That makes this function have side effects, which is not desired.
            //
            // It also makes reference tracking on temporary keychains broken, since the cert can
            // DangerousRelease a handle it didn't DangerousAddRef on.  And so CopyWithPrivateKey makes
            // a temporary keychain, then deletes it before anyone has a chance to (e.g.) export the
            // new identity as a PKCS#12 blob.
            //
            // Solution: Clone the cert, like we do in Windows.
            SafeSecCertificateHandle tempHandle;

            {
                byte[]                export     = RawData;
                const bool            exportable = false;
                SafeSecIdentityHandle identityHandle;
                tempHandle = Interop.AppleCrypto.X509ImportCertificate(
                    export,
                    X509ContentType.Cert,
                    SafePasswordHandle.InvalidHandle,
                    cloneKeychain,
                    exportable,
                    out identityHandle);

                Debug.Assert(identityHandle.IsInvalid, "identityHandle should be IsInvalid");
                identityHandle.Dispose();

                Debug.Assert(!tempHandle.IsInvalid, "tempHandle should not be IsInvalid");
            }

            using (keychain)
                using (tempHandle)
                {
                    SafeSecIdentityHandle identityHandle = Interop.AppleCrypto.X509CopyWithPrivateKey(
                        tempHandle,
                        keyPair.PrivateKey,
                        keychain);

                    AppleCertificatePal newPal = new AppleCertificatePal(identityHandle);
                    return(newPal);
                }
        }
示例#23
0
 private static extern int AppleCryptoNative_X509DemuxAndRetainHandle(
     IntPtr handle,
     out SafeSecCertificateHandle certHandle,
     out SafeSecIdentityHandle identityHandle);
示例#24
0
 private static extern int AppleCryptoNative_X509CopyCertFromIdentity(
     SafeSecIdentityHandle identity,
     out SafeSecCertificateHandle cert);
 private static extern int AppleCryptoNative_X509MoveToKeychain(
     SafeSecCertificateHandle certHandle,
     SafeKeychainHandle targetKeychain,
     SafeSecKeyRefHandle privateKeyHandle,
     out SafeSecIdentityHandle pIdentityHandleOut,
     out int pOSStatus);
示例#26
0
 private static partial int AppleCryptoNative_X509CopyWithPrivateKey(
     SafeSecCertificateHandle certHandle,
     SafeSecKeyRefHandle privateKeyHandle,
     SafeKeychainHandle targetKeychain,
     out SafeSecIdentityHandle pIdentityHandleOut,
     out int pOSStatus);
示例#27
0
        internal static SafeSecCertificateHandle X509ImportCertificate(
            byte[] bytes,
            X509ContentType contentType,
            SafePasswordHandle importPassword,
            SafeKeychainHandle keychain,
            bool exportable,
            out SafeSecIdentityHandle identityHandle)
        {
            SafeSecCertificateHandle certHandle;
            int osStatus;
            int ret;

            SafeCreateHandle cfPassphrase    = s_nullExportString;
            bool             releasePassword = false;

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

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

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

                SafeTemporaryKeychainHandle.TrackItem(certHandle);
                SafeTemporaryKeychainHandle.TrackItem(identityHandle);
            }
            finally
            {
                if (releasePassword)
                {
                    importPassword.DangerousRelease();
                }

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

            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();
            }
        }
示例#28
0
 private static extern int AppleCryptoNative_X509CopyPrivateKeyFromIdentity(
     SafeSecIdentityHandle identity,
     out SafeSecKeyRefHandle key);