Skip to content

Commit

Permalink
Implement iOS PAL for S.S.C.X509Certificates
Browse files Browse the repository at this point in the history
  • Loading branch information
filipnavara authored May 19, 2021
1 parent 84b88e7 commit d3e9a11
Show file tree
Hide file tree
Showing 53 changed files with 2,964 additions and 993 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.Apple;

using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
internal static partial class AppleCrypto
{
[DllImport(Libraries.AppleCryptoNative)]
private static extern int AppleCryptoNative_SecKeychainEnumerateCerts(
out SafeCFArrayHandle matches);

[DllImport(Libraries.AppleCryptoNative)]
private static extern int AppleCryptoNative_SecKeychainEnumerateIdentities(
out SafeCFArrayHandle matches);

[DllImport(Libraries.AppleCryptoNative)]
private static extern int AppleCryptoNative_X509StoreAddCertificate(
SafeHandle certOrIdentity);

[DllImport(Libraries.AppleCryptoNative)]
private static extern int AppleCryptoNative_X509StoreRemoveCertificate(
SafeHandle certOrIdentity,
bool isReadOnlyMode);

internal static SafeCFArrayHandle KeychainEnumerateCerts()
{
SafeCFArrayHandle matches;
int osStatus = AppleCryptoNative_SecKeychainEnumerateCerts(out matches);

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

matches.Dispose();
throw CreateExceptionForOSStatus(osStatus);
}

internal static SafeCFArrayHandle KeychainEnumerateIdentities()
{
SafeCFArrayHandle matches;
int osStatus = AppleCryptoNative_SecKeychainEnumerateIdentities(out matches);

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

matches.Dispose();
throw CreateExceptionForOSStatus(osStatus);
}

internal static void X509StoreAddCertificate(SafeHandle certOrIdentity)
{
int osStatus = AppleCryptoNative_X509StoreAddCertificate(certOrIdentity);

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

internal static void X509StoreRemoveCertificate(SafeHandle certOrIdentity, bool isReadOnlyMode)
{
const int errSecItemNotFound = -25300;

int osStatus = AppleCryptoNative_X509StoreRemoveCertificate(certOrIdentity, isReadOnlyMode);

if (osStatus == 0 && isReadOnlyMode)
{
// The certificate exists in the store otherwise we would get errSecItemNotFound error
throw new CryptographicException(SR.Cryptography_X509_StoreReadOnly);
}

if (osStatus != 0 && osStatus != errSecItemNotFound)
{
throw CreateExceptionForOSStatus(osStatus);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,19 @@ private static extern int AppleCryptoNative_SecKeychainEnumerateIdentities(
out SafeCFArrayHandle matches,
out int pOSStatus);

[DllImport(Libraries.AppleCryptoNative)]
private static extern int AppleCryptoNative_X509StoreAddCertificate(
SafeKeychainItemHandle cert,
SafeKeychainHandle keychain,
out int pOSStatus);

[DllImport(Libraries.AppleCryptoNative)]
private static extern int AppleCryptoNative_X509StoreRemoveCertificate(
SafeKeychainItemHandle cert,
SafeKeychainHandle keychain,
bool isReadOnlyMode,
out int pOSStatus);

private static SafeKeychainHandle SecKeychainItemCopyKeychain(SafeHandle item)
{
bool addedRef = false;
Expand Down Expand Up @@ -290,6 +303,54 @@ internal static void SecKeychainDelete(IntPtr handle, bool throwOnError=true)
throw CreateExceptionForOSStatus(osStatus);
}
}

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();
}
}

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();
}
}
}
}

Expand Down
Loading

0 comments on commit d3e9a11

Please sign in to comment.