internal static byte[] X509GetRawData(SafeSecCertificateHandle cert) { int osStatus; SafeCFDataHandle data; int ret = AppleCryptoNative_X509GetRawData( cert, out data, out osStatus); using (data) { if (ret == 1) { return(CoreFoundation.CFGetData(data)); } if (ret == 0) { throw CreateExceptionForOSStatus(osStatus); } Debug.Fail($"Unexpected return value {ret}"); throw new CryptographicException(); } }
private static partial int AppleCryptoNative_X509ImportCertificate( ref byte pbKeyBlob, int cbKeyBlob, X509ContentType contentType, SafeCreateHandle cfPfxPassphrase, out SafeSecCertificateHandle pCertOut, out SafeSecIdentityHandle pPrivateKeyOut);
internal static SafeSecIdentityHandle X509CopyWithPrivateKey( SafeSecCertificateHandle certHandle, SafeSecKeyRefHandle privateKeyHandle, SafeKeychainHandle targetKeychain) { SafeSecIdentityHandle identityHandle; int osStatus; int result = AppleCryptoNative_X509CopyWithPrivateKey( certHandle, privateKeyHandle, targetKeychain, out identityHandle, out osStatus); if (result == 1) { Debug.Assert(!identityHandle.IsInvalid); return(identityHandle); } identityHandle.Dispose(); if (result == 0) { throw CreateExceptionForOSStatus(osStatus); } Debug.Fail($"AppleCryptoNative_X509CopyWithPrivateKey returned {result}"); throw new CryptographicException(); }
internal static AppleCertificatePal ImportPkcs12(UnixPkcs12Reader.CertAndKey certAndKey) { AppleCertificatePal pal = (AppleCertificatePal)certAndKey.Cert !; if (certAndKey.Key != null) { AppleCertificateExporter exporter = new AppleCertificateExporter(new TempExportPal(pal), certAndKey.Key); byte[] smallPfx = exporter.Export(X509ContentType.Pkcs12, s_passwordExportHandle) !; SafeSecIdentityHandle identityHandle; SafeSecCertificateHandle certHandle = Interop.AppleCrypto.X509ImportCertificate( smallPfx, X509ContentType.Pkcs12, s_passwordExportHandle, out identityHandle); if (identityHandle.IsInvalid) { identityHandle.Dispose(); return(new AppleCertificatePal(certHandle)); } certHandle.Dispose(); return(new AppleCertificatePal(identityHandle)); } return(pal); }
internal static void X509StoreRemoveCertificate(SafeSecCertificateHandle certHandle, SafeKeychainHandle keychain) { int osStatus; int ret = AppleCryptoNative_X509StoreRemoveCertificate(certHandle, keychain, out osStatus); if (ret == 0) { throw CreateExceptionForOSStatus(osStatus); } const int SuccessOrNoMatch = 1; const int UserTrustExists = 2; const int AdminTrustExists = 3; switch (ret) { case SuccessOrNoMatch: break; case UserTrustExists: throw new CryptographicException(SR.Cryptography_X509Store_WouldModifyUserTrust); case AdminTrustExists: throw new CryptographicException(SR.Cryptography_X509Store_WouldModifyAdminTrust); default: Debug.Fail($"Unexpected result from AppleCryptoNative_X509StoreRemoveCertificate: {ret}"); throw new CryptographicException(); } }
internal static ICertificatePal ImportPkcs12NonExportable( AppleCertificatePal cert, SafeSecKeyRefHandle privateKey, SafePasswordHandle password, SafeKeychainHandle keychain) { Pkcs12SmallExport exporter = new Pkcs12SmallExport(new TempExportPal(cert), privateKey); byte[] smallPfx = exporter.Export(X509ContentType.Pkcs12, password) !; SafeSecIdentityHandle identityHandle; SafeSecCertificateHandle certHandle = Interop.AppleCrypto.X509ImportCertificate( smallPfx, X509ContentType.Pkcs12, password, keychain, exportable: false, out identityHandle); // On Windows and Linux if a PFX uses a LocalKeyId to bind the wrong key to a cert, the // nonsensical object of "this cert, that key" is returned. // // On macOS, because we can't forge CFIdentityRefs without the keychain, we're subject to // Apple's more stringent matching of a consistent keypair. if (identityHandle.IsInvalid) { identityHandle.Dispose(); return(new AppleCertificatePal(certHandle)); } certHandle.Dispose(); return(new AppleCertificatePal(identityHandle)); }
public static SafeSecIdentityHandle GetIdentity(X509Certificate certificate, out SafeSecCertificateHandle[] intermediateCerts) { var identity = GetIdentity(certificate); var impl2 = certificate.Impl as X509Certificate2Impl; if (impl2 == null || impl2.IntermediateCertificates == null) { intermediateCerts = new SafeSecCertificateHandle [0]; return(identity); } intermediateCerts = new SafeSecCertificateHandle [impl2.IntermediateCertificates.Count]; try { for (int i = 0; i < intermediateCerts.Length; i++) { intermediateCerts [i] = MonoCertificatePal.FromOtherCertificate(impl2.IntermediateCertificates[i]); } return(identity); } catch { for (int i = 0; i < intermediateCerts.Length; i++) { intermediateCerts [i]?.Dispose(); } identity?.Dispose(); throw; } }
internal AppleCertificatePal(SafeSecIdentityHandle identityHandle) { Debug.Assert(!identityHandle.IsInvalid); _identityHandle = identityHandle; _certHandle = Interop.AppleCrypto.X509GetCertFromIdentity(identityHandle); }
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);
public void Dispose() { _certHandle?.Dispose(); _identityHandle?.Dispose(); _certHandle = null !; _identityHandle = null; DisposeTempKeychain(); }
public void Dispose() { _certHandle?.Dispose(); _identityHandle?.Dispose(); _privateKeyHolder?.Dispose(); _certHandle = null; _identityHandle = null; _privateKeyHolder = null; }
internal static ICertificatePal FromDerBlob( ReadOnlySpan <byte> rawData, X509ContentType contentType, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); bool ephemeralSpecified = keyStorageFlags.HasFlag(X509KeyStorageFlags.EphemeralKeySet); if (contentType == X509ContentType.Pkcs7) { throw new CryptographicException( SR.Cryptography_X509_PKCS7_Unsupported, new PlatformNotSupportedException(SR.Cryptography_X509_PKCS7_Unsupported)); } if (contentType == X509ContentType.Pkcs12) { if ((keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable) { throw new PlatformNotSupportedException(SR.Cryptography_X509_PKCS12_ExportableNotSupported); } if ((keyStorageFlags & X509KeyStorageFlags.PersistKeySet) == X509KeyStorageFlags.PersistKeySet) { throw new PlatformNotSupportedException(SR.Cryptography_X509_PKCS12_PersistKeySetNotSupported); } return(ImportPkcs12(rawData, password, ephemeralSpecified)); } SafeSecIdentityHandle identityHandle; SafeSecCertificateHandle certHandle = Interop.AppleCrypto.X509ImportCertificate( rawData, contentType, password, 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(); }
internal static SafeSecIdentityHandle X509MoveToKeychain( SafeSecCertificateHandle cert, SafeKeychainHandle targetKeychain, SafeSecKeyRefHandle privateKey) { SafeSecIdentityHandle identityHandle; int osStatus; int result = AppleCryptoNative_X509MoveToKeychain( cert, targetKeychain, privateKey ?? SafeSecKeyRefHandle.InvalidHandle, out identityHandle, out osStatus); if (result == 0) { identityHandle.Dispose(); throw CreateExceptionForOSStatus(osStatus); } if (result != 1) { Debug.Fail($"AppleCryptoNative_X509MoveToKeychain returned {result}"); throw new CryptographicException(); } if (privateKey?.IsInvalid == false) { // If a PFX has a mismatched association between a private key and the // certificate public key then MoveToKeychain will write the NULL SecIdentityRef // (after cleaning up the temporary key). // // When that happens, just treat the import as public-only. if (!identityHandle.IsInvalid) { return(identityHandle); } } // If the cert in the PFX had no key, but it was imported with PersistKeySet (imports into // the default keychain) and a matching private key was already there, then an // identityHandle could be found. But that's not desirable, since neither Windows or Linux would // do that matching. // // So dispose the handle, no matter what. identityHandle.Dispose(); return(null); }
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)); }
public void Dispose() { _certHandle?.Dispose(); _identityHandle?.Dispose(); _certHandle = null !; _identityHandle = null; SafeKeychainHandle?tempKeychain = Interlocked.Exchange(ref _tempKeychain, null); if (tempKeychain != null) { tempKeychain.Dispose(); } }
public static SafeSecIdentityHandle FindIdentity(SafeSecCertificateHandle certificate, bool throwOnError = false) { if (certificate == null || certificate.IsInvalid) { throw new ObjectDisposedException(nameof(certificate)); } var identity = FindIdentity(cert => MonoCertificatePal.Equals(certificate, cert)) ?? new SafeSecIdentityHandle(); if (!throwOnError || identity.IsInvalid) { return(identity); } var subject = MonoCertificatePal.GetSubjectSummary(certificate); throw new InvalidOperationException($"Could not find SecIdentity for certificate '{subject}' in keychain."); }
internal static ICertificatePal FromDerBlob( ReadOnlySpan <byte> rawData, X509ContentType contentType, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); bool ephemeralSpecified = keyStorageFlags.HasFlag(X509KeyStorageFlags.EphemeralKeySet); if (contentType == X509ContentType.Pkcs7) { throw new CryptographicException( SR.Cryptography_X509_PKCS7_Unsupported, new PlatformNotSupportedException(SR.Cryptography_X509_PKCS7_Unsupported)); } if (contentType == X509ContentType.Pkcs12) { // TODO: // We ignore keyStorageFlags which is tracked in https://github.com/dotnet/runtime/issues/52434. // The keys are always imported as ephemeral and never persisted. Exportability is ignored for // the moment and it needs to be investigated how to map it to iOS keychain primitives. return(ImportPkcs12(rawData, password, ephemeralSpecified)); } SafeSecIdentityHandle identityHandle; SafeSecCertificateHandle certHandle = Interop.AppleCrypto.X509ImportCertificate( rawData, contentType, password, 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(); }
public static string GetSubjectSummary(SafeSecCertificateHandle certificate) { if (certificate == null || certificate.IsInvalid) { throw new ArgumentNullException(nameof(certificate)); } var subjectSummaryHandle = IntPtr.Zero; try { subjectSummaryHandle = SecCertificateCopySubjectSummary(certificate.DangerousGetHandle()); return(CFString.AsString(subjectSummaryHandle)); } finally { if (subjectSummaryHandle != IntPtr.Zero) { CFObject.CFRelease(subjectSummaryHandle); } } }
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(); } }
public SecStatusCode SetAnchorCertificates(X509CertificateCollection certificates) { if (handle == IntPtr.Zero) { throw new ObjectDisposedException("SecTrust"); } if (certificates == null) { return(SecTrustSetAnchorCertificates(handle, IntPtr.Zero)); } var array = new SafeSecCertificateHandle [certificates.Count]; int i = 0; foreach (var certificate in certificates) { array [i++] = MonoCertificatePal.FromOtherCertificate(certificate); } return(SetAnchorCertificates(array)); }
protected override ICertificatePalCore ReadX509Der(ReadOnlyMemory <byte> data) { SafeSecCertificateHandle certHandle = Interop.AppleCrypto.X509ImportCertificate( data.Span, X509ContentType.Cert, SafePasswordHandle.InvalidHandle, out SafeSecIdentityHandle 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(); }
public static byte[] GetRawData(SafeSecCertificateHandle certificate) { if (certificate == null || certificate.IsInvalid) { throw new ArgumentNullException(nameof(certificate)); } var dataPtr = SecCertificateCopyData(certificate.DangerousGetHandle()); if (dataPtr == IntPtr.Zero) { throw new ArgumentException("Not a valid certificate"); } using (var data = new CFData(dataPtr, true)) { var buffer = new byte[(int)data.Length]; Marshal.Copy(data.Bytes, buffer, 0, buffer.Length); return(buffer); } }
public SecTrust(X509CertificateCollection certificates, SecPolicy policy) { if (certificates == null) { throw new ArgumentNullException("certificates"); } var array = new SafeSecCertificateHandle [certificates.Count]; int i = 0; foreach (var certificate in certificates) { array [i++] = MonoCertificatePal.FromOtherCertificate(certificate); } Initialize(array, policy); for (i = 0; i < array.Length; i++) { array [i].Dispose(); } }
internal static SafeSecKeyRefHandle X509GetPublicKey(SafeSecCertificateHandle cert) { SafeSecKeyRefHandle publicKey; int osStatus; int ret = AppleCryptoNative_X509GetPublicKey(cert, out publicKey, out osStatus); if (ret == 1) { return(publicKey); } publicKey.Dispose(); if (ret == 0) { throw CreateExceptionForOSStatus(osStatus); } Debug.Fail($"Unexpected return value {ret}"); throw new CryptographicException(); }
internal static string?X509GetSubjectSummary(SafeSecCertificateHandle cert) { SafeCFStringHandle subjectSummary; int ret = AppleCryptoNative_X509GetSubjectSummary( cert, out subjectSummary); using (subjectSummary) { if (ret == 1) { return(CoreFoundation.CFStringToString(subjectSummary)); } } if (ret == 0) { return(null); } Debug.Fail($"Unexpected return value {ret}"); throw new CryptographicException(); }
public static ICertificatePal FromBlob( 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); } bool exportable = true; SafeKeychainHandle keychain; if (contentType == X509ContentType.Pkcs12) { if ((keyStorageFlags & X509KeyStorageFlags.EphemeralKeySet) == X509KeyStorageFlags.EphemeralKeySet) { throw new PlatformNotSupportedException(SR.Cryptography_X509_NoEphemeralPfx); } exportable = (keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable; bool persist = (keyStorageFlags & X509KeyStorageFlags.PersistKeySet) == X509KeyStorageFlags.PersistKeySet; keychain = persist ? Interop.AppleCrypto.SecKeychainCopyDefault() : Interop.AppleCrypto.CreateTemporaryKeychain(); } else { keychain = SafeTemporaryKeychainHandle.InvalidHandle; password = SafePasswordHandle.InvalidHandle; } using (keychain) { SafeSecIdentityHandle identityHandle; SafeSecCertificateHandle certHandle = Interop.AppleCrypto.X509ImportCertificate( rawData, contentType, password, keychain, exportable, out identityHandle); if (identityHandle.IsInvalid) { identityHandle.Dispose(); return(new AppleCertificatePal(certHandle)); } if (contentType != X509ContentType.Pkcs12) { Debug.Fail("Non-PKCS12 import produced an identity handle"); identityHandle.Dispose(); certHandle.Dispose(); throw new CryptographicException(); } Debug.Assert(certHandle.IsInvalid); certHandle.Dispose(); return(new AppleCertificatePal(identityHandle)); } }
internal AppleCertificatePal(SafeSecCertificateHandle certHandle) { Debug.Assert(!certHandle.IsInvalid); _certHandle = certHandle; }
private static extern int AppleCryptoNative_X509DemuxAndRetainHandle( IntPtr handle, out SafeSecCertificateHandle certHandle, out SafeSecIdentityHandle identityHandle);
private static extern int AppleCryptoNative_X509CopyCertFromIdentity( SafeSecIdentityHandle identity, out SafeSecCertificateHandle cert);