Пример #1
0
        private static ILoaderPal ImportPkcs12(
            ReadOnlySpan <byte> rawData,
            SafePasswordHandle password,
            bool exportable,
            bool ephemeralSpecified,
            SafeKeychainHandle keychain)
        {
            ApplePkcs12Reader reader = new ApplePkcs12Reader(rawData);

            try
            {
                reader.Decrypt(password, ephemeralSpecified);
                return(new ApplePkcs12CertLoader(reader, keychain, password, exportable));
            }
            catch
            {
                reader.Dispose();
                keychain.Dispose();
                throw;
            }
        }
 private static int AppleCryptoNative_X509ImportCertificate(
     ReadOnlySpan <byte> keyBlob,
     X509ContentType contentType,
     SafeCreateHandle cfPfxPassphrase,
     SafeKeychainHandle tmpKeychain,
     int exportable,
     out SafeSecCertificateHandle pCertOut,
     out SafeSecIdentityHandle pPrivateKeyOut,
     out int pOSStatus)
 {
     return(AppleCryptoNative_X509ImportCertificate(
                ref MemoryMarshal.GetReference(keyBlob),
                keyBlob.Length,
                contentType,
                cfPfxPassphrase,
                tmpKeychain,
                exportable,
                out pCertOut,
                out pPrivateKeyOut,
                out pOSStatus));
 }
Пример #3
0
        internal static SafeCFArrayHandle KeychainEnumerateCerts(SafeKeychainHandle keychainHandle)
        {
            SafeCFArrayHandle matches;
            int osStatus;
            int result = AppleCryptoNative_SecKeychainEnumerateCerts(keychainHandle, out matches, out osStatus);

            if (result == 1)
            {
                return(matches);
            }

            matches.Dispose();

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

            Debug.Fail($"Unexpected result from AppleCryptoNative_SecKeychainEnumerateCerts: {result}");
            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();
            }
        }
Пример #5
0
 private static partial int AppleCryptoNative_SecKeychainItemCopyKeychain(
     IntPtr item,
     out SafeKeychainHandle keychain);
Пример #6
0
        public static ICertificatePal FromBlob(
            ReadOnlySpan <byte> rawData,
            SafePasswordHandle password,
            X509KeyStorageFlags keyStorageFlags)
        {
            Debug.Assert(password != null);

            X509ContentType contentType = X509Certificate2.GetCertContentType(rawData);

            if (contentType == X509ContentType.Pkcs7)
            {
                // In single mode for a PKCS#7 signed or signed-and-enveloped file we're supposed to return
                // the certificate which signed the PKCS#7 file.
                //
                // X509Certificate2Collection::Export(X509ContentType.Pkcs7) claims to be a signed PKCS#7,
                // but doesn't emit a signature block. So this is hard to test.
                //
                // TODO(2910): Figure out how to extract the signing certificate, when it's present.
                throw new CryptographicException(SR.Cryptography_X509_PKCS7_NoSigner);
            }

            if (contentType == X509ContentType.Pkcs12)
            {
                if ((keyStorageFlags & X509KeyStorageFlags.EphemeralKeySet) == X509KeyStorageFlags.EphemeralKeySet)
                {
                    throw new PlatformNotSupportedException(SR.Cryptography_X509_NoEphemeralPfx);
                }

                bool exportable = (keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable;

                bool persist =
                    (keyStorageFlags & X509KeyStorageFlags.PersistKeySet) == X509KeyStorageFlags.PersistKeySet;

                SafeKeychainHandle keychain = persist
                    ? Interop.AppleCrypto.SecKeychainCopyDefault()
                    : Interop.AppleCrypto.CreateTemporaryKeychain();

                using (keychain)
                {
                    AppleCertificatePal ret = ImportPkcs12(rawData, password, exportable, keychain);
                    if (!persist)
                    {
                        // If we used temporary keychain we need to prevent deletion.
                        // on 10.15+ if keychain is unlinked, certain certificate operations may fail.
                        bool success = false;
                        keychain.DangerousAddRef(ref success);
                        if (success)
                        {
                            ret._tempKeychain = keychain;
                        }
                    }

                    return(ret);
                }
            }

            SafeSecIdentityHandle    identityHandle;
            SafeSecCertificateHandle certHandle = Interop.AppleCrypto.X509ImportCertificate(
                rawData,
                contentType,
                SafePasswordHandle.InvalidHandle,
                SafeTemporaryKeychainHandle.InvalidHandle,
                exportable: true,
                out identityHandle);

            if (identityHandle.IsInvalid)
            {
                identityHandle.Dispose();
                return(new AppleCertificatePal(certHandle));
            }

            Debug.Fail("Non-PKCS12 import produced an identity handle");

            identityHandle.Dispose();
            certHandle.Dispose();
            throw new CryptographicException();
        }
Пример #7
0
 private static partial int AppleCryptoNative_X509StoreAddCertificate(
     SafeKeychainItemHandle cert,
     SafeKeychainHandle keychain,
     out int pOSStatus);
Пример #8
0
 private static partial int AppleCryptoNative_SetKeychainNeverLock(SafeKeychainHandle keychain);
Пример #9
0
 private static partial int AppleCryptoNative_SecKeychainOpen(
     string keychainPath,
     out SafeKeychainHandle keychain);
Пример #10
0
        internal static void X509StoreRemoveCertificate(SafeKeychainItemHandle certHandle, SafeKeychainHandle keychain, bool isReadOnlyMode)
        {
            int osStatus;
            int ret = AppleCryptoNative_X509StoreRemoveCertificate(certHandle, keychain, isReadOnlyMode, out osStatus);

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

            const int SuccessOrNoMatch = 1;
            const int UserTrustExists  = 2;
            const int AdminTrustExists = 3;
            const int ReadOnlyDelete   = 4;

            switch (ret)
            {
            case SuccessOrNoMatch:
                break;

            case UserTrustExists:
                throw new CryptographicException(SR.Cryptography_X509Store_WouldModifyUserTrust);

            case AdminTrustExists:
                throw new CryptographicException(SR.Cryptography_X509Store_WouldModifyAdminTrust);

            case ReadOnlyDelete:
                throw new CryptographicException(SR.Cryptography_X509_StoreReadOnly);

            default:
                Debug.Fail($"Unexpected result from AppleCryptoNative_X509StoreRemoveCertificate: {ret}");
                throw new CryptographicException();
            }
        }
 private static extern int AppleCryptoNative_X509MoveToKeychain(
     SafeSecCertificateHandle certHandle,
     SafeKeychainHandle targetKeychain,
     SafeSecKeyRefHandle privateKeyHandle,
     out SafeSecIdentityHandle pIdentityHandleOut,
     out int pOSStatus);
        internal static SafeCFArrayHandle X509ImportCollection(
            byte[] bytes,
            X509ContentType contentType,
            SafePasswordHandle importPassword,
            SafeKeychainHandle keychain,
            bool exportable)
        {
            SafeCreateHandle cfPassphrase    = s_nullExportString;
            bool             releasePassword = false;

            int ret;
            SafeCFArrayHandle collectionHandle;
            int osStatus;

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

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

                ret = AppleCryptoNative_X509ImportCollection(
                    bytes,
                    bytes.Length,
                    contentType,
                    cfPassphrase,
                    keychain,
                    exportable ? 1 : 0,
                    out collectionHandle,
                    out osStatus);

                if (ret == 1)
                {
                    return(collectionHandle);
                }
            }
            finally
            {
                if (releasePassword)
                {
                    importPassword.DangerousRelease();
                }

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

            collectionHandle.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();
            }
        }
Пример #13
0
 public void Dispose()
 {
     _keychainHandle?.Dispose();
     _keychainHandle = null !;
 }
Пример #14
0
 private static extern int AppleCryptoNative_RsaGenerateKey(
     int keySizeInBits,
     SafeKeychainHandle keychain,
     out SafeSecKeyRefHandle pPublicKey,
     out SafeSecKeyRefHandle pPrivateKey,
     out int pOSStatus);
Пример #15
0
 private static partial int AppleCryptoNative_X509StoreRemoveCertificate(
     SafeKeychainItemHandle cert,
     SafeKeychainHandle keychain,
     [MarshalAs(UnmanagedType.Bool)] bool isReadOnlyMode,
     out int pOSStatus);
Пример #16
0
 private static partial int AppleCryptoNative_SecKeychainCreate(
     string path,
     int utf8PassphraseLength,
     byte[] utf8Passphrase,
     out SafeKeychainHandle keychain);
Пример #17
0
        internal static void X509StoreAddCertificate(SafeKeychainItemHandle certOrIdentity, SafeKeychainHandle keychain)
        {
            int osStatus;
            int ret = AppleCryptoNative_X509StoreAddCertificate(certOrIdentity, keychain, out osStatus);

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

            if (ret != 1)
            {
                Debug.Fail($"Unexpected result from AppleCryptoNative_X509StoreAddCertificate: {ret}");
                throw new CryptographicException();
            }
        }
 private static extern int AppleCryptoNative_X509StoreRemoveCertificate(
     SafeKeychainItemHandle cert,
     SafeKeychainHandle keychain,
     out int pOSStatus);
Пример #19
0
 private static partial int AppleCryptoNative_SecKeychainCopyDefault(out SafeKeychainHandle keychain);
Пример #20
0
 private static extern int AppleCryptoNative_SetKeychainNeverLock(SafeKeychainHandle keychain);
Пример #21
0
 private static partial int AppleCryptoNative_SecKeychainUnlock(
     SafeKeychainHandle keychain,
     int utf8PassphraseLength,
     byte[] utf8Passphrase);
Пример #22
0
 private static extern int AppleCryptoNative_SecKeychainEnumerateCerts(
     SafeKeychainHandle keychain,
     out SafeCFArrayHandle matches,
     out int pOSStatus);
Пример #23
0
 private static partial int AppleCryptoNative_SecKeychainEnumerateIdentities(
     SafeKeychainHandle keychain,
     out SafeCFArrayHandle matches,
     out int pOSStatus);
Пример #24
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);
                }
        }
Пример #25
0
 private static partial int AppleCryptoNative_X509StoreRemoveCertificate(
     SafeKeychainItemHandle cert,
     SafeKeychainHandle keychain,
     bool isReadOnlyMode,
     out int pOSStatus);
Пример #26
0
 private static partial int AppleCryptoNative_X509CopyWithPrivateKey(
     SafeSecCertificateHandle certHandle,
     SafeSecKeyRefHandle privateKeyHandle,
     SafeKeychainHandle targetKeychain,
     out SafeSecIdentityHandle pIdentityHandleOut,
     out int pOSStatus);