Ejemplo n.º 1
0
        internal static SafeTemporaryKeychainHandle CreateTemporaryKeychain()
        {
            string tmpKeychainPath = Path.Combine(
                Path.GetTempPath(),
                Guid.NewGuid().ToString("N") + ".keychain");

            // Use a distinct GUID so that if a keychain is abandoned it isn't recoverable.
            string tmpKeychainPassphrase = Guid.NewGuid().ToString("N");

            byte[] utf8Passphrase = System.Text.Encoding.UTF8.GetBytes(tmpKeychainPassphrase);

            SafeTemporaryKeychainHandle keychain;

            int osStatus = AppleCryptoNative_SecKeychainCreateTemporary(
                tmpKeychainPath,
                utf8Passphrase.Length,
                utf8Passphrase,
                out keychain);

            SafeTemporaryKeychainHandle.TrackKeychain(keychain);

            if (osStatus == 0)
            {
                osStatus = AppleCryptoNative_SetKeychainNeverLock(keychain);
            }

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

            return(keychain);
        }
Ejemplo n.º 2
0
        internal static unsafe SafeTemporaryKeychainHandle CreateTemporaryKeychain()
        {
            const int randomSize      = 256;
            string    tmpKeychainPath = Path.Combine(
                Path.GetTempPath(),
                Guid.NewGuid().ToString("N") + ".keychain");

            // Use a random password so that if a keychain is abandoned it isn't recoverable.
            // We use stack to minimize lingering
            Span <byte> random = stackalloc byte[randomSize];

            RandomNumberGenerator.Fill(random);

            // Create hex-like UTF8 string.
            Span <byte> utf8Passphrase = stackalloc byte[randomSize * 2 + 1];

            utf8Passphrase[randomSize * 2] = 0; // null termination for C string.

            for (int i = 0; i < random.Length; i++)
            {
                // Instead of true hexadecimal, we simply take lower and upper 4 bits and we offset them from ASCII 'A'
                // to get printable form. We dont use managed string to avoid lingering copies.
                utf8Passphrase[i * 2]     = (byte)((random[i] & 0x0F) + 65);
                utf8Passphrase[i * 2 + 1] = (byte)((random[i] >> 4) & 0x0F + 65);
            }

            // clear the binary bits.
            CryptographicOperations.ZeroMemory(random);

            SafeTemporaryKeychainHandle keychain;
            int osStatus;

            fixed(byte *ptr = utf8Passphrase)
            {
                osStatus = AppleCryptoNative_SecKeychainCreateTemporary(
                    tmpKeychainPath,
                    utf8Passphrase.Length,
                    ptr,
                    out keychain);
            }

            CryptographicOperations.ZeroMemory(utf8Passphrase);
            SafeTemporaryKeychainHandle.TrackKeychain(keychain);

            if (osStatus == 0)
            {
                osStatus = AppleCryptoNative_SetKeychainNeverLock(keychain);
            }

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

            return(keychain);
        }
        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();
            }
        }
        internal static SafeSecKeyRefHandle X509GetPrivateKeyFromIdentity(SafeSecIdentityHandle identity)
        {
            SafeSecKeyRefHandle key;
            int osStatus = AppleCryptoNative_X509CopyPrivateKeyFromIdentity(identity, out key);

            SafeTemporaryKeychainHandle.TrackItem(key);

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

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

            return(key);
        }
        internal static SafeSecCertificateHandle X509GetCertFromIdentity(SafeSecIdentityHandle identity)
        {
            SafeSecCertificateHandle cert;
            int osStatus = AppleCryptoNative_X509CopyCertFromIdentity(identity, out cert);

            SafeTemporaryKeychainHandle.TrackItem(cert);

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

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

            return(cert);
        }
Ejemplo n.º 6
0
        internal static void RsaGenerateKey(
            int keySizeInBits,
            out SafeSecKeyRefHandle pPublicKey,
            out SafeSecKeyRefHandle pPrivateKey)
        {
            using (SafeTemporaryKeychainHandle tempKeychain = CreateTemporaryKeychain())
            {
                SafeSecKeyRefHandle keychainPublic;
                SafeSecKeyRefHandle keychainPrivate;
                int osStatus;

                int result = AppleCryptoNative_RsaGenerateKey(
                    keySizeInBits,
                    tempKeychain,
                    out keychainPublic,
                    out keychainPrivate,
                    out osStatus);

                if (result == 1)
                {
                    pPublicKey  = keychainPublic;
                    pPrivateKey = keychainPrivate;
                    return;
                }

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

                        Debug.Fail($"Unexpected result from AppleCryptoNative_RsaGenerateKey: {result}");
                        throw new CryptographicException();
                    }
            }
        }
        internal static bool X509DemuxAndRetainHandle(
            IntPtr handle,
            out SafeSecCertificateHandle certHandle,
            out SafeSecIdentityHandle identityHandle)
        {
            int result = AppleCryptoNative_X509DemuxAndRetainHandle(handle, out certHandle, out identityHandle);

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

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

            case 0:
                return(false);

            default:
                Debug.Fail($"AppleCryptoNative_X509DemuxAndRetainHandle returned {result}");
                throw new CryptographicException();
            }
        }
        internal static SafeSecKeyRefHandle X509GetPublicKey(SafeSecCertificateHandle cert)
        {
            SafeSecKeyRefHandle publicKey;
            int osStatus;
            int ret = AppleCryptoNative_X509GetPublicKey(cert, out publicKey, out osStatus);

            SafeTemporaryKeychainHandle.TrackItem(publicKey);

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

            publicKey.Dispose();

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

            Debug.Fail($"Unexpected return value {ret}");
            throw new CryptographicException();
        }
Ejemplo n.º 9
0
 private static unsafe partial int AppleCryptoNative_SecKeychainCreateTemporary(
     string path,
     int utf8PassphraseLength,
     byte *utf8Passphrase,
     out SafeTemporaryKeychainHandle keychain);
Ejemplo n.º 10
0
 private static extern int AppleCryptoNative_SecKeychainCreateTemporary(
     string path,
     int utf8PassphraseLength,
     byte[] utf8Passphrase,
     out SafeTemporaryKeychainHandle keychain);
Ejemplo n.º 11
0
 public AppleCertLoader(SafeCFArrayHandle collectionHandle, SafeTemporaryKeychainHandle tmpKeychain)
 {
     _collectionHandle = collectionHandle;
     _tmpKeychain      = tmpKeychain;
 }
Ejemplo n.º 12
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();
            }
        }