diff --git a/src/Security/Certificate.cs b/src/Security/Certificate.cs index 4736a6f65bdb..d42518dcbf92 100644 --- a/src/Security/Certificate.cs +++ b/src/Security/Certificate.cs @@ -658,6 +658,206 @@ public SecStatusCode Decrypt (SecPadding padding, byte [] cipherText, out byte [ return _Decrypt (padding, cipherText, ref plainText); } + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + [DllImport (Constants.SecurityLibrary)] + static extern IntPtr /* SecKeyRef _Nullable */ SecKeyCreateRandomKey (IntPtr /* CFDictionaryRef* */ parameters, out IntPtr /* CFErrorRef** */ error); + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + static public SecKey CreateRandomKey (NSDictionary parameters, out NSError error) + { + if (parameters == null) + throw new ArgumentNullException (nameof (parameters)); + + IntPtr err; + var key = SecKeyCreateRandomKey (parameters.Handle, out err); + error = err == IntPtr.Zero ? null : new NSError (err); + return key == IntPtr.Zero ? null : new SecKey (key, true); + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + static public SecKey CreateRandomKey (SecKeyType keyType, int keySizeInBits, NSDictionary parameters, out NSError error) + { + using (var ks = new NSNumber (keySizeInBits)) + using (var md = parameters == null ? new NSMutableDictionary () : new NSMutableDictionary (parameters)) { + md.LowlevelSetObject (keyType.GetConstant (), SecAttributeKey.KeyType); + md.LowlevelSetObject (ks, SecAttributeKey.KeySizeInBits); + return CreateRandomKey (md, out error); + } + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + [DllImport (Constants.SecurityLibrary)] + static extern IntPtr /* SecKeyRef _Nullable */ SecKeyCreateWithData (IntPtr /* CFDataRef* */ keyData, IntPtr /* CFDictionaryRef* */ attributes, out IntPtr /* CFErrorRef** */ error); + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + static public SecKey Create (NSData keyData, NSDictionary parameters, out NSError error) + { + if (keyData == null) + throw new ArgumentNullException (nameof (keyData)); + if (parameters == null) + throw new ArgumentNullException (nameof (parameters)); + + IntPtr err; + var key = SecKeyCreateWithData (keyData.Handle, parameters.Handle, out err); + error = err == IntPtr.Zero ? null : new NSError (err); + return key == IntPtr.Zero ? null : new SecKey (key, true); + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + static public SecKey Create (NSData keyData, SecKeyType keyType, SecKeyClass keyClass, int keySizeInBits, NSDictionary parameters, out NSError error) + { + using (var ks = new NSNumber (keySizeInBits)) + using (var md = parameters == null ? new NSMutableDictionary () : new NSMutableDictionary (parameters)) { + md.LowlevelSetObject (keyType.GetConstant (), SecAttributeKey.KeyType); + md.LowlevelSetObject (keyClass.GetConstant (), SecAttributeKey.KeyClass); + md.LowlevelSetObject (ks, SecAttributeKey.KeySizeInBits); + return Create (keyData, md, out error); + } + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + [DllImport (Constants.SecurityLibrary)] + static extern IntPtr /* CFDataRef _Nullable */ SecKeyCopyExternalRepresentation (IntPtr /* SecKeyRef* */ key, out IntPtr /* CFErrorRef** */ error); + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + public NSData GetExternalRepresentation (out NSError error) + { + IntPtr err; + var data = SecKeyCopyExternalRepresentation (handle, out err); + error = err == IntPtr.Zero ? null : new NSError (err); + return Runtime.GetNSObject (data, true); + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + public NSData GetExternalRepresentation () + { + IntPtr err; + var data = SecKeyCopyExternalRepresentation (handle, out err); + return Runtime.GetNSObject (data, true); + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + [DllImport (Constants.SecurityLibrary)] + static extern IntPtr /* CFDictionaryRef _Nullable */ SecKeyCopyAttributes (IntPtr /* SecKeyRef* */ key); + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + public NSDictionary GetAttributes () + { + var dict = SecKeyCopyAttributes (handle); + return Runtime.GetNSObject (dict, true); + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + [DllImport (Constants.SecurityLibrary)] + static extern IntPtr /* SecKeyRef* */ SecKeyCopyPublicKey (IntPtr /* SecKeyRef* */ key); + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + public SecKey GetPublicKey () + { + var key = SecKeyCopyPublicKey (handle); + return key == IntPtr.Zero ? null : new SecKey (key, true); + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + [DllImport (Constants.SecurityLibrary)] + static extern bool /* Boolean */ SecKeyIsAlgorithmSupported (IntPtr /* SecKeyRef* */ key, /* SecKeyOperationType */ nint operation, IntPtr /* SecKeyAlgorithm* */ algorithm); + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + public bool IsAlgorithmSupported (SecKeyOperationType operation, SecKeyAlgorithm algorithm) + { + return SecKeyIsAlgorithmSupported (handle, (int) operation, algorithm.GetConstant ().Handle); + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + [DllImport (Constants.SecurityLibrary)] + static extern /* CFDataRef _Nullable */ IntPtr SecKeyCreateSignature (/* SecKeyRef */ IntPtr key, /* SecKeyAlgorithm */ IntPtr algorithm, /* CFDataRef */ IntPtr dataToSign, /* CFErrorRef* */ out IntPtr error); + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + public NSData CreateSignature (SecKeyAlgorithm algorithm, NSData dataToSign, out NSError error) + { + if (dataToSign == null) + throw new ArgumentNullException (nameof (dataToSign)); + + IntPtr err; + var data = SecKeyCreateSignature (Handle, algorithm.GetConstant ().Handle, dataToSign.Handle, out err); + error = err == IntPtr.Zero ? null : new NSError (err); + return Runtime.GetNSObject (data, true); + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + [DllImport (Constants.SecurityLibrary)] + static extern /* Boolean */ bool SecKeyVerifySignature (/* SecKeyRef */ IntPtr key, /* SecKeyAlgorithm */ IntPtr algorithm, /* CFDataRef */ IntPtr signedData, /* CFDataRef */ IntPtr signature, /* CFErrorRef* */ out IntPtr error); + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + public bool VerifySignature (SecKeyAlgorithm algorithm, NSData signedData, NSData signature, out NSError error) + { + if (signedData == null) + throw new ArgumentNullException (nameof (signedData)); + if (signature == null) + throw new ArgumentNullException (nameof (signature)); + + IntPtr err; + var result = SecKeyVerifySignature (Handle, algorithm.GetConstant ().Handle, signedData.Handle, signature.Handle, out err); + error = err == IntPtr.Zero ? null : new NSError (err); + return result; + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + [DllImport (Constants.SecurityLibrary)] + static extern /* CFDataRef _Nullable */ IntPtr SecKeyCreateEncryptedData (/* SecKeyRef */ IntPtr key, /* SecKeyAlgorithm */ IntPtr algorithm, /* CFDataRef */ IntPtr plaintext, /* CFErrorRef* */ out IntPtr error); + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + public NSData CreateEncryptedData (SecKeyAlgorithm algorithm, NSData plaintext, out NSError error) + { + if (plaintext == null) + throw new ArgumentNullException (nameof (plaintext)); + + IntPtr err; + var data = SecKeyCreateEncryptedData (Handle, algorithm.GetConstant ().Handle, plaintext.Handle, out err); + error = err == IntPtr.Zero ? null : new NSError (err); + return Runtime.GetNSObject (data, true); + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + [DllImport (Constants.SecurityLibrary)] + static extern /* CFDataRef _Nullable */ IntPtr SecKeyCreateDecryptedData (/* SecKeyRef */ IntPtr key, /* SecKeyAlgorithm */ IntPtr algorithm, /* CFDataRef */ IntPtr ciphertext, /* CFErrorRef* */ out IntPtr error); + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + public NSData CreateDecryptedData (SecKeyAlgorithm algorithm, NSData ciphertext, out NSError error) + { + if (ciphertext == null) + throw new ArgumentNullException (nameof (ciphertext)); + + IntPtr err; + var data = SecKeyCreateDecryptedData (Handle, algorithm.GetConstant ().Handle, ciphertext.Handle, out err); + error = err == IntPtr.Zero ? null : new NSError (err); + return Runtime.GetNSObject (data, true); + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + [DllImport (Constants.SecurityLibrary)] + static extern /* CFDataRef _Nullable */ IntPtr SecKeyCopyKeyExchangeResult (/* SecKeyRef */ IntPtr privateKey, /* SecKeyAlgorithm */ IntPtr algorithm, /* SecKeyRef */ IntPtr publicKey, /* CFDictionaryRef */ IntPtr parameters, /* CFErrorRef* */ out IntPtr error); + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + public NSData GetKeyExchangeResult (SecKeyAlgorithm algorithm, SecKey publicKey, NSDictionary parameters, out NSError error) + { + if (publicKey == null) + throw new ArgumentNullException (nameof (publicKey)); + if (parameters == null) + throw new ArgumentNullException (nameof (parameters)); + + IntPtr err; + var data = SecKeyCopyKeyExchangeResult (Handle, algorithm.GetConstant ().Handle, publicKey.Handle, parameters.Handle, out err); + error = err == IntPtr.Zero ? null : new NSError (err); + return Runtime.GetNSObject (data, true); + } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + public NSData GetKeyExchangeResult (SecKeyAlgorithm algorithm, SecKey publicKey, SecKeyKeyExchangeParameter parameters, out NSError error) + { + return GetKeyExchangeResult (algorithm, publicKey, parameters?.Dictionary, out error); + } + ~SecKey () { Dispose (false); diff --git a/src/Security/Enums.cs b/src/Security/Enums.cs index c3ee770301bf..f07cbb235709 100644 --- a/src/Security/Enums.cs +++ b/src/Security/Enums.cs @@ -293,7 +293,9 @@ public enum SecStatusCode { MissingAttributeWrappedKeyFormat = -67805, /* A wrapped key format attribute was missing. */ StagedOperationInProgress = -67806, /* A staged operation is in progress. */ StagedOperationNotStarted = -67807, /* A staged operation was not started. */ +#endif VerifyFailed = -67808, /* A cryptographic verification failure has occurred. */ +#if MONOMAC QuerySizeUnknown = -67809, /* The query size is unknown. */ BlockSizeMismatch = -67810, /* A block size mismatch occurred. */ PublicKeyInconsistent = -67811, /* The public key was inconsistent. */ @@ -410,7 +412,7 @@ public enum SecTrustResult { Invalid, Proceed, - [Availability (Deprecated = Platform.iOS_7_0)] + [Availability (Deprecated = Platform.iOS_7_0 | Platform.Mac_10_9)] Confirm, Deny, Unspecified, @@ -441,4 +443,14 @@ public enum SecTokenID { [Field ("kSecAttrTokenIDSecureEnclave")] SecureEnclave, } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + [Native] + public enum SecKeyOperationType : nint { + Sign = 0, + Verify = 1, + Encrypt = 2, + Decrypt = 3, + KeyExchange = 4 + } } diff --git a/src/Security/Items.cs b/src/Security/Items.cs index a40b65e427ac..4f575a773509 100644 --- a/src/Security/Items.cs +++ b/src/Security/Items.cs @@ -73,16 +73,6 @@ public enum SecAuthenticationType { Ntlm, Msn, Dpa, Rpa, HttpBasic, HttpDigest, HtmlForm, Default } - public enum SecKeyClass { - Invalid = -1, - Public, Private, Symmetric - } - - public enum SecKeyType { - Invalid = -1, - RSA, EC - } - #if XAMCORE_2_0 public class SecKeyChain : INativeObject { @@ -1206,17 +1196,14 @@ public SecKeyClass KeyClass { var k = Fetch (SecAttributeKey.KeyClass); if (k == IntPtr.Zero) return SecKeyClass.Invalid; - if (CFType.Equal (k, ClassKeys.Public)) - return SecKeyClass.Public; - else if (CFType.Equal (k, ClassKeys.Private)) - return SecKeyClass.Private; - else if (CFType.Equal (k, ClassKeys.Symmetric)) - return SecKeyClass.Symmetric; - else - return SecKeyClass.Invalid; + using (var s = new NSString (k)) + return SecKeyClassExtensions.GetValue (s); } set { - SetValue (value == SecKeyClass.Public ? ClassKeys.Public : value == SecKeyClass.Private ? ClassKeys.Private : ClassKeys.Symmetric, SecAttributeKey.KeyClass); + var k = value.GetConstant (); + if (k == null) + throw new ArgumentException ("Unknown value"); + SetValue ((NSObject) k, SecAttributeKey.KeyClass); } } @@ -1257,16 +1244,15 @@ public SecKeyType KeyType { var k = Fetch (SecAttributeKey.KeyType); if (k == IntPtr.Zero) return SecKeyType.Invalid; - if (CFType.Equal (k, KeyTypeKeys.RSA)) - return SecKeyType.RSA; - else if (CFType.Equal (k, KeyTypeKeys.EC)) - return SecKeyType.EC; - else - return SecKeyType.Invalid; + using (var s = new NSString (k)) + return SecKeyTypeExtensions.GetValue (s); } set { - SetValue (value == SecKeyType.RSA ? KeyTypeKeys.RSA : KeyTypeKeys.EC, SecAttributeKey.KeyType); + var k = value.GetConstant (); + if (k == null) + throw new ArgumentException ("Unknown value"); + SetValue ((NSObject) k, SecAttributeKey.KeyType); } } diff --git a/src/Security/SecAccessControl.cs b/src/Security/SecAccessControl.cs index 17f7ab91b1cf..2f232c499adb 100644 --- a/src/Security/SecAccessControl.cs +++ b/src/Security/SecAccessControl.cs @@ -20,10 +20,15 @@ namespace XamCore.Security { - // CFIndex -> SecAccessControl.h [Flags] [Native] +#if XAMCORE_4_0 + // changed to CFOptionFlags in Xcode 8 SDK + public enum SecAccessControlCreateFlags : nuint { +#else + // CFOptionFlags -> SecAccessControl.h public enum SecAccessControlCreateFlags : nint { +#endif UserPresence = 1 << 0, TouchIDAny = 1 << 1, TouchIDCurrentSet = 1 << 3, diff --git a/src/Security/SecPolicy.cs b/src/Security/SecPolicy.cs index 9e14d53b3d88..492083cc9204 100644 --- a/src/Security/SecPolicy.cs +++ b/src/Security/SecPolicy.cs @@ -34,27 +34,29 @@ public partial class SecPolicy { [iOS (7,0)] [DllImport (Constants.SecurityLibrary)] - extern static IntPtr /* CFDictionaryRef */ SecPolicyCopyProperties (IntPtr /* SecPolicyRef */ policyRef); + extern static IntPtr /* __nullable CFDictionaryRef */ SecPolicyCopyProperties (IntPtr /* SecPolicyRef */ policyRef); [iOS (7,0)] public NSDictionary GetProperties () { - return new NSDictionary (SecPolicyCopyProperties (Handle), true); + var dict = SecPolicyCopyProperties (Handle); + return Runtime.GetNSObject (dict, true); } [Mac (10,9)] [DllImport (Constants.SecurityLibrary)] - extern static IntPtr /* SecPolicyRef */ SecPolicyCreateRevocation (/* CFOptionFlags */ nuint revocationFlags); + extern static IntPtr /* __nullable SecPolicyRef */ SecPolicyCreateRevocation (/* CFOptionFlags */ nuint revocationFlags); [Mac (10,9)][iOS (7,0)] static public SecPolicy CreateRevocationPolicy (SecRevocation revocationFlags) { - return new SecPolicy (SecPolicyCreateRevocation ((nuint)(ulong) revocationFlags), true); + var policy = SecPolicyCreateRevocation ((nuint)(ulong) revocationFlags); + return policy == IntPtr.Zero ? null : new SecPolicy (policy, true); } [Mac (10,9)][iOS (7,0)] [DllImport (Constants.SecurityLibrary)] - extern static IntPtr /* SecPolicyRef */ SecPolicyCreateWithProperties (IntPtr /* CFTypeRef */ policyIdentifier, IntPtr /* CFDictionaryRef */ properties); + extern static IntPtr /* __nullable SecPolicyRef */ SecPolicyCreateWithProperties (IntPtr /* CFTypeRef */ policyIdentifier, IntPtr /* CFDictionaryRef */ properties); [Mac (10,9)][iOS (7,0)] static public SecPolicy CreatePolicy (NSString policyIdentifier, NSDictionary properties) diff --git a/src/Security/SecSharedCredential.cs b/src/Security/SecSharedCredential.cs index 195ec8c44769..8c8f59842393 100644 --- a/src/Security/SecSharedCredential.cs +++ b/src/Security/SecSharedCredential.cs @@ -136,4 +136,4 @@ public static string CreateSharedWebCredentialPassword () } -#endif //!MONOMAC && !WATCH +#endif // IOS diff --git a/src/Security/SecureTransport.cs b/src/Security/SecureTransport.cs index 336926a92570..9e575f1e8737 100644 --- a/src/Security/SecureTransport.cs +++ b/src/Security/SecureTransport.cs @@ -1,6 +1,7 @@ // Copyright 2014 Xamarin Inc. All rights reserved. using System; +using XamCore.ObjCRuntime; namespace XamCore.Security { @@ -85,23 +86,27 @@ public enum SslStatus { // Security.framework/Headers/SecureTransport.h // untyped enum public enum SslSessionOption { - // 10.6+ / iOS5+ BreakOnServerAuth, BreakOnCertRequested, - // 10.8+ / iOS5+ + [Mac (10,8)] BreakOnClientAuth, - // 10.9+ / iOS7+ + + [iOS (7,0)][Mac (10,9)] FalseStart, + SendOneByteRecord, - // 10.11 / iOS9.0, + [iOS (9,0)][Mac (10,11)] AllowServerIdentityChange = 5, - // 10.10 / iOS8.1+ + [iOS (8,1)][Mac (10,10)] Fallback = 6, - // 10.11 / iOS9.0 - BreakOnClientHello + [iOS (9,0)][Mac (10,11)] + BreakOnClientHello = 7, + + [iOS (10,0)][Mac (10,12)] + AllowRenegotiation = 8, } // Security.framework/Headers/SecureTransport.h diff --git a/src/Security/SslContext.cs b/src/Security/SslContext.cs index 58f274845d2e..a424a65ab9a0 100644 --- a/src/Security/SslContext.cs +++ b/src/Security/SslContext.cs @@ -4,11 +4,12 @@ // Authors: // Sebastien Pouliot // -// Copyright 2014-2015 Xamarin Inc. +// Copyright 2014-2016 Xamarin Inc. // using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Runtime.InteropServices; using System.Text; @@ -469,18 +470,17 @@ T Convert (IntPtr p) } #endif [DllImport (Constants.SecurityLibrary)] - extern unsafe static /* OSStatus */ SslStatus SSLSetCertificate (/* SSLContextRef */ IntPtr context, /* CFArrayRef */ IntPtr certRefs); + extern unsafe static /* OSStatus */ SslStatus SSLSetCertificate (/* SSLContextRef */ IntPtr context, /* _Nullable CFArrayRef */ IntPtr certRefs); NSArray Bundle (SecIdentity identity, IEnumerable certificates) { - if (identity == null) - throw new ArgumentNullException ("identity"); - int i = 0; + int i = identity == null ? 0 : 1; int n = certificates == null ? 0 : certificates.Count (); - var ptrs = new IntPtr [n + 1]; - ptrs [0] = identity.Handle; + var ptrs = new IntPtr [n + i]; + if (i == 1) + ptrs [0] = identity.Handle; foreach (var certificate in certificates) - ptrs [++i] = certificate.Handle; + ptrs [i++] = certificate.Handle; return NSArray.FromIntPtrs (ptrs); } @@ -548,5 +548,56 @@ public SslStatus SetSessionStrengthPolicy (SslSessionStrengthPolicy policyStreng Console.WriteLine ("SetSessionStrengthPolicy is not available anymore."); return SslStatus.Success; } + + [iOS (10,0)][Mac (10,12)] + [DllImport (Constants.SecurityLibrary)] + static extern int SSLSetSessionConfig (IntPtr /* SSLContextRef* */ context, IntPtr /* CFStringRef* */ config); + + [iOS (10,0)][Mac (10,12)] + [EditorBrowsable (EditorBrowsableState.Advanced)] + public int SetSessionConfig (NSString config) + { + if (config == null) + throw new ArgumentNullException (nameof (config)); + + return SSLSetSessionConfig (Handle, config.Handle); + } + + [iOS (10,0)][Mac (10,12)] + public int SetSessionConfig (SslSessionConfig config) + { + return SetSessionConfig (config.GetConstant ()); + } + + [iOS (10,0)][Mac (10,12)] + [DllImport (Constants.SecurityLibrary)] + static extern int SSLReHandshake (IntPtr /* SSLContextRef* */ context); + + [iOS (10,0)][Mac (10,12)] + public int ReHandshake () + { + return SSLReHandshake (Handle); + } + + [iOS (9,0)][Mac (10,11)] + [DllImport (Constants.SecurityLibrary)] + static extern /* OSStatus */ SslStatus SSLCopyRequestedPeerName (IntPtr /* SSLContextRef* */ context, byte[] /* char* */ peerName, ref nuint /* size_t */ peerNameLen); + + [iOS (9,0)][Mac (10,11)] + [DllImport (Constants.SecurityLibrary)] + static extern /* OSStatus */ SslStatus SSLCopyRequestedPeerNameLength (IntPtr /* SSLContextRef* */ context, ref nuint /* size_t */ peerNameLen); + + [iOS (9,0)][Mac (10,11)] + public string GetRequestedPeerName () + { + var result = String.Empty; + nuint length = 0; + if (SSLCopyRequestedPeerNameLength (Handle, ref length) == SslStatus.Success) { + var bytes = new byte [length]; + if (SSLCopyRequestedPeerName (Handle, bytes, ref length) == SslStatus.Success) + result = Encoding.UTF8.GetString (bytes); + } + return result; + } } } diff --git a/src/Security/Trust.cs b/src/Security/Trust.cs index adbbb01a1550..d6b4cc2bdc2b 100644 --- a/src/Security/Trust.cs +++ b/src/Security/Trust.cs @@ -192,7 +192,7 @@ public NSData GetExceptions () [Mac (10,9)] [DllImport (Constants.SecurityLibrary)] - extern static bool SecTrustSetExceptions (IntPtr /* SecTrustRef */ trust, IntPtr /* CFDataRef */ exceptions); + extern static bool SecTrustSetExceptions (IntPtr /* SecTrustRef */ trust, IntPtr /* __nullable CFDataRef */ exceptions); [Mac (10,9)] public bool SetExceptions (NSData data) diff --git a/src/security.cs b/src/security.cs index 12120aa9e291..3d8f0dc2cadf 100644 --- a/src/security.cs +++ b/src/security.cs @@ -59,6 +59,10 @@ interface SecPolicyIdentifier { [Field ("kSecPolicyAppleRevocation")] NSString AppleRevocation { get; } + [iOS (7,0)][Mac (10,9)] + [Field ("kSecPolicyApplePassbookSigning")] + NSString ApplePassbookSigning { get; } + [Mac(10,11), iOS (9,0)] [Field ("kSecPolicyApplePayIssuerEncryption")] NSString ApplePayIssuerEncryption { get; } @@ -79,6 +83,10 @@ interface SecPolicyPropertyKey { [Mavericks] [Field ("kSecPolicyRevocationFlags")] NSString RevocationFlags { get; } + + [iOS (7,0)][Mac (10,9)] + [Field ("kSecPolicyTeamIdentifier")] + NSString TeamIdentifier { get; } } [Static] @@ -122,9 +130,13 @@ interface SecTrustResultKey { NSString RevocationValidUntilDate { get; } [iOS (9,0)] - [NoMac] + [Mac (10,12)] // headers says 10.11 but it's not present in 10.11 [Field ("kSecTrustCertificateTransparency")] NSString CertificateTransparency { get; } + + [iOS (10,0)][Mac (10,12)] + [Field ("kSecTrustCertificateTransparencyWhiteList")] + NSString CertificateTransparencyWhiteList { get; } } [Static] @@ -136,26 +148,33 @@ interface SecMatchLimit { IntPtr MatchLimitAll { get; } } - [Static][Internal] - interface KeyTypeKeys { + enum SecKeyType { + Invalid = -1, + [Field ("kSecAttrKeyTypeRSA")] - IntPtr RSA { get; } + RSA = 0, [Mac (10,9)] [Field ("kSecAttrKeyTypeEC")] - IntPtr EC { get; } + EC = 1, + + [iOS (10,0)] + [Mac (10,12)] + [Field ("kSecAttrKeyTypeECSECPrimeRandom")] + ECSecPrimeRandom = 2, } - [Static][Internal] - interface ClassKeys { + enum SecKeyClass { + Invalid = -1, + [Field ("kSecAttrKeyClassPublic")] - IntPtr Public { get; } + Public = 0, [Field ("kSecAttrKeyClassPrivate")] - IntPtr Private { get; } + Private = 1, [Field ("kSecAttrKeyClassSymmetric")] - IntPtr Symmetric { get; } + Symmetric = 2, } [Static][Internal] @@ -459,9 +478,19 @@ interface SecAttributeKey { IntPtr CanUnwrap { get; } [iOS (9,0)] - [NoMac] + [Mac (10,12)] [Field ("kSecAttrTokenID")] IntPtr TokenID { get; } + + [iOS (9,0)] + [NoMac] + [Field ("kSecAttrTokenIDSecureEnclave")] + IntPtr SecureEnclave { get; } + + [iOS (10,0)] + [Mac (10,12)] + [Field ("kSecAttrAccessGroupToken")] + IntPtr AccessGroupToken { get; } } [Static][Internal] @@ -607,4 +636,233 @@ interface SecPropertyKey [Field ("kSecPropertyKeyValue")] IntPtr Value { get; } } + + [Watch (3,0)][TV (10,0)][Mac (10,12)][iOS (10,0)] + enum SecKeyAlgorithm { + [Field ("kSecKeyAlgorithmRSASignatureRaw")] + RsaSignatureRaw, + + [Field ("kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw")] + RsaSignatureDigestPkcs1v15Raw, + + [Field ("kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1")] + RsaSignatureDigestPkcs1v15Sha1, + + [Field ("kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224")] + RsaSignatureDigestPkcs1v15Sha224, + + [Field ("kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256")] + RsaSignatureDigestPkcs1v15Sha256, + + [Field ("kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384")] + RsaSignatureDigestPkcs1v15Sha384, + + [Field ("kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512")] + RsaSignatureDigestPkcs1v15Sha512, + + [Field ("kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1")] + RsaSignatureMessagePkcs1v15Sha1, + + [Field ("kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224")] + RsaSignatureMessagePkcs1v15Sha224, + + [Field ("kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256")] + RsaSignatureMessagePkcs1v15Sha256, + + [Field ("kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384")] + RsaSignatureMessagePkcs1v15Sha384, + + [Field ("kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512")] + RsaSignatureMessagePkcs1v15Sha512, + + [Field ("kSecKeyAlgorithmECDSASignatureRFC4754")] + EcdsaSignatureRfc4754, + + [Field ("kSecKeyAlgorithmECDSASignatureDigestX962")] + EcdsaSignatureDigestX962, + + [Field ("kSecKeyAlgorithmECDSASignatureDigestX962SHA1")] + EcdsaSignatureDigestX962Sha1, + + [Field ("kSecKeyAlgorithmECDSASignatureDigestX962SHA224")] + EcdsaSignatureDigestX962Sha224, + + [Field ("kSecKeyAlgorithmECDSASignatureDigestX962SHA256")] + EcdsaSignatureDigestX962Sha256, + + [Field ("kSecKeyAlgorithmECDSASignatureDigestX962SHA384")] + EcdsaSignatureDigestX962Sha384, + + [Field ("kSecKeyAlgorithmECDSASignatureDigestX962SHA512")] + EcdsaSignatureDigestX962Sha512, + + [Field ("kSecKeyAlgorithmECDSASignatureMessageX962SHA1")] + EcdsaSignatureMessageX962Sha1, + + [Field ("kSecKeyAlgorithmECDSASignatureMessageX962SHA224")] + EcdsaSignatureMessageX962Sha224, + + [Field ("kSecKeyAlgorithmECDSASignatureMessageX962SHA256")] + EcdsaSignatureMessageX962Sha256, + + [Field ("kSecKeyAlgorithmECDSASignatureMessageX962SHA384")] + EcdsaSignatureMessageX962Sha384, + + [Field ("kSecKeyAlgorithmECDSASignatureMessageX962SHA512")] + EcdsaSignatureMessageX962Sha512, + + [Field ("kSecKeyAlgorithmRSAEncryptionRaw")] + RsaEncryptionRaw, + + [Field ("kSecKeyAlgorithmRSAEncryptionPKCS1")] + RsaEncryptionPkcs1, + + [Field ("kSecKeyAlgorithmRSAEncryptionOAEPSHA1")] + RsaEncryptionOaepSha1, + + [Field ("kSecKeyAlgorithmRSAEncryptionOAEPSHA224")] + RsaEncryptionOaepSha224, + + [Field ("kSecKeyAlgorithmRSAEncryptionOAEPSHA256")] + RsaEncryptionOaepSha256, + + [Field ("kSecKeyAlgorithmRSAEncryptionOAEPSHA384")] + RsaEncryptionOaepSha384, + + [Field ("kSecKeyAlgorithmRSAEncryptionOAEPSHA512")] + RsaEncryptionOaepSha512, + + [Field ("kSecKeyAlgorithmRSAEncryptionOAEPSHA1AESGCM")] + RsaEncryptionOaepSha1AesCgm, + + [Field ("kSecKeyAlgorithmRSAEncryptionOAEPSHA224AESGCM")] + RsaEncryptionOaepSha224AesGcm, + + [Field ("kSecKeyAlgorithmRSAEncryptionOAEPSHA256AESGCM")] + RsaEncryptionOaepSha256AesGcm, + + [Field ("kSecKeyAlgorithmRSAEncryptionOAEPSHA384AESGCM")] + RsaEncryptionOaepSha384AesGcm, + + [Field ("kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM")] + RsaEncryptionOaepSha512AesGcm, + + [Field ("kSecKeyAlgorithmECIESEncryptionStandardX963SHA1AESGCM")] + EciesEncryptionStandardX963Sha1AesGcm, + + [Field ("kSecKeyAlgorithmECIESEncryptionStandardX963SHA224AESGCM")] + EciesEncryptionStandardX963Sha224AesGcm, + + [Field ("kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM")] + EciesEncryptionStandardX963Sha256AesGcm, + + [Field ("kSecKeyAlgorithmECIESEncryptionStandardX963SHA384AESGCM")] + EciesEncryptionStandardX963Sha384AesGcm, + + [Field ("kSecKeyAlgorithmECIESEncryptionStandardX963SHA512AESGCM")] + EciesEncryptionStandardX963Sha512AesGcm, + + [Field ("kSecKeyAlgorithmECIESEncryptionCofactorX963SHA1AESGCM")] + EciesEncryptionCofactorX963Sha1AesGcm, + + [Field ("kSecKeyAlgorithmECIESEncryptionCofactorX963SHA224AESGCM")] + EciesEncryptionCofactorX963Sha224AesGcm, + + [Field ("kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM")] + EciesEncryptionCofactorX963Sha256AesGcm, + + [Field ("kSecKeyAlgorithmECIESEncryptionCofactorX963SHA384AESGCM")] + EciesEncryptionCofactorX963Sha384AesGcm, + + [Field ("kSecKeyAlgorithmECIESEncryptionCofactorX963SHA512AESGCM")] + EciesEncryptionCofactorX963Sha512AesGcm, + + [Field ("kSecKeyAlgorithmECDHKeyExchangeStandard")] + EcdhKeyExchangeStandard, + + [Field ("kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1")] + EcdhKeyExchangeStandardX963Sha1, + + [Field ("kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224")] + EcdhKeyExchangeStandardX963Sha224, + + [Field ("kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256")] + EcdhKeyExchangeStandardX963Sha256, + + [Field ("kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384")] + EcdhKeyExchangeStandardX963Sha384, + + [Field ("kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512")] + EcdhKeyExchangeStandardX963Sha512, + + [Field ("kSecKeyAlgorithmECDHKeyExchangeCofactor")] + EcdhKeyExchangeCofactor, + + [Field ("kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1")] + EcdhKeyExchangeCofactorX963Sha1, + + [Field ("kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224")] + EcdhKeyExchangeCofactorX963Sha224, + + [Field ("kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256")] + EcdhKeyExchangeCofactorX963Sha256, + + [Field ("kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384")] + EcdhKeyExchangeCofactorX963Sha384, + + [Field ("kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512")] + EcdhKeyExchangeCofactorX963Sha512, + } + + [iOS (10,0)][TV (10,0)][Watch (3,0)][Mac (10,12)] + enum SslSessionConfig { + [Field ("kSSLSessionConfig_default")] + Default, + + [Field ("kSSLSessionConfig_ATSv1")] + Ats1, + + [Field ("kSSLSessionConfig_ATSv1_noPFS")] + Ats1NoPfs, + + [Field ("kSSLSessionConfig_standard")] + Standard, + + [Field ("kSSLSessionConfig_RC4_fallback")] + RC4Fallback, + + [Field ("kSSLSessionConfig_TLSv1_fallback")] + Tls1Fallback, + + [Field ("kSSLSessionConfig_TLSv1_RC4_fallback")] + Tls1RC4Fallback, + + [Field ("kSSLSessionConfig_legacy")] + Legacy, + + [Field ("kSSLSessionConfig_legacy_DHE")] + LegacyDhe, + + [Field ("kSSLSessionConfig_anonymous")] + Anonymous, + } + + [iOS (10,0)][TV (10,0)][Watch (3,0)][Mac (10,12)] + [Internal][Static] + interface SecKeyKeyExchangeParameterKey { + [Field ("kSecKeyKeyExchangeParameterRequestedSize")] + NSString RequestedSizeKey { get; } + + [Field ("kSecKeyKeyExchangeParameterSharedInfo")] + NSString SharedInfoKey { get; } + } + + [iOS (10,0)][TV (10,0)][Watch (3,0)][Mac (10,12)] + [StrongDictionary ("SecKeyKeyExchangeParameterKey")] + interface SecKeyKeyExchangeParameter { + + int RequestedSize { get; set; } + + NSData SharedInfo { get; set; } + } } diff --git a/tests/introspection/ApiTypoTest.cs b/tests/introspection/ApiTypoTest.cs index 58842fe242e2..04e14c083ed8 100644 --- a/tests/introspection/ApiTypoTest.cs +++ b/tests/introspection/ApiTypoTest.cs @@ -75,6 +75,7 @@ public virtual bool Skip (MemberInfo methodName, string typo) { "Arraycollation", "Asin", "Atan", + "Ats", // App Transport Security "Attrib", "Attributevalue", "Audiofile", @@ -146,8 +147,10 @@ public virtual bool Skip (MemberInfo methodName, string typo) { "Dtmf", // DTMF "dy", "Ebu", - "Ecc", + "Ecc", // Elliptic Curve Cryptography + "Ecdh", // Elliptic Curve Diffie–Hellman "Ecdsa", // Elliptic Curve Digital Signature Algorithm + "Ecies", // Elliptic Curve Integrated Encryption Scheme "Eof", // acronym End-Of-File "Emagic", "Emaili", diff --git a/tests/monotouch-test/Security/KeyTest.cs b/tests/monotouch-test/Security/KeyTest.cs index 845c3156a20e..9263e7b2955a 100644 --- a/tests/monotouch-test/Security/KeyTest.cs +++ b/tests/monotouch-test/Security/KeyTest.cs @@ -90,6 +90,7 @@ public void Encrypt_New () [Test] public void RoundtripRSA512PKCS1 () { + NSError error; SecKey private_key; SecKey public_key; using (var record = new SecRecord (SecKind.Key)) { @@ -100,10 +101,51 @@ public void RoundtripRSA512PKCS1 () byte [] plain = new byte [20] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; byte [] cipher; + if (TestRuntime.CheckXcodeVersion (8,0)) { + Assert.True (public_key.IsAlgorithmSupported (SecKeyOperationType.Encrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), "public/IsAlgorithmSupported/Encrypt"); + // I would have expect false + Assert.True (public_key.IsAlgorithmSupported (SecKeyOperationType.Decrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), "public/IsAlgorithmSupported/Decrypt"); + + using (var pub = public_key.GetPublicKey ()) { + // a new native instance of the key is returned (so having a new managed SecKey is fine) + Assert.That (pub.Handle, Is.Not.EqualTo (public_key.Handle), "public/GetPublicKey"); + } + using (var attrs = public_key.GetAttributes ()) { + Assert.That (attrs.Count, Is.GreaterThan (0), "public/GetAttributes"); + } + using (var data = public_key.GetExternalRepresentation (out error)) { + Assert.Null (error, "public/error-1"); + Assert.NotNull (data, "public/GetExternalRepresentation"); + + using (var key = SecKey.Create (data, SecKeyType.RSA, SecKeyClass.Public, 512, null, out error)) { + Assert.Null (error, "public/Create/error-1"); + } + } + } Assert.That (public_key.Encrypt (SecPadding.PKCS1, plain, out cipher), Is.EqualTo (SecStatusCode.Success), "Encrypt"); - public_key.Dispose (); byte[] result; + if (TestRuntime.CheckXcodeVersion (8,0)) { + Assert.False (private_key.IsAlgorithmSupported (SecKeyOperationType.Encrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), "private/IsAlgorithmSupported/Encrypt"); + Assert.True (private_key.IsAlgorithmSupported (SecKeyOperationType.Decrypt, SecKeyAlgorithm.RsaEncryptionPkcs1), "private/IsAlgorithmSupported/Decrypt"); + + using (var pub2 = private_key.GetPublicKey ()) { + // a new native instance of the key is returned (so having a new managed SecKey is fine) + Assert.That (pub2.Handle, Is.Not.EqualTo (public_key.Handle), "private/GetPublicKey"); + } + using (var attrs = private_key.GetAttributes ()) { + Assert.That (attrs.Count, Is.GreaterThan (0), "private/GetAttributes"); + } + using (var data2 = private_key.GetExternalRepresentation (out error)) { + Assert.Null (error, "private/error-1"); + Assert.NotNull (data2, "private/GetExternalRepresentation"); + + using (var key = SecKey.Create (data2, SecKeyType.RSA, SecKeyClass.Private, 512, null, out error)) { + Assert.Null (error, "private/Create/error-1"); + } + } + } + public_key.Dispose (); Assert.That (private_key.Decrypt (SecPadding.PKCS1, cipher, out result), Is.EqualTo (SecStatusCode.Success), "Decrypt"); Assert.That (plain, Is.EqualTo (result), "match"); private_key.Dispose (); @@ -143,10 +185,19 @@ public void RoundtripRSA1024OAEP () byte [] plain = new byte [0]; byte [] cipher; + if (TestRuntime.CheckXcodeVersion (8,0)) { + Assert.True (public_key.IsAlgorithmSupported (SecKeyOperationType.Encrypt, SecKeyAlgorithm.RsaEncryptionOaepSha1), "public/IsAlgorithmSupported/Encrypt"); + // I would have expect false + Assert.True (public_key.IsAlgorithmSupported (SecKeyOperationType.Decrypt, SecKeyAlgorithm.RsaEncryptionOaepSha1), "public/IsAlgorithmSupported/Decrypt"); + } Assert.That (public_key.Encrypt (SecPadding.OAEP, plain, out cipher), Is.EqualTo (SecStatusCode.Success), "Encrypt"); public_key.Dispose (); byte[] result; + if (TestRuntime.CheckXcodeVersion (8,0)) { + Assert.False (private_key.IsAlgorithmSupported (SecKeyOperationType.Encrypt, SecKeyAlgorithm.RsaEncryptionOaepSha1), "private/IsAlgorithmSupported/Encrypt"); + Assert.True (private_key.IsAlgorithmSupported (SecKeyOperationType.Decrypt, SecKeyAlgorithm.RsaEncryptionOaepSha1), "private/IsAlgorithmSupported/Decrypt"); + } Assert.That (private_key.Decrypt (SecPadding.OAEP, cipher, out result), Is.EqualTo (SecStatusCode.Success), "Decrypt"); Assert.That (plain, Is.EqualTo (result), "match"); private_key.Dispose (); @@ -309,5 +360,109 @@ public void BenchmarkNative4096 () public_key.Dispose (); } } + + [Test] + public void RSA () + { + TestRuntime.AssertXcodeVersion (8, 0); + NSError error; + using (var key = SecKey.CreateRandomKey (SecKeyType.RSA, 512, null, out error)) { + Assert.Null (error, "RSA/error"); + + using (var data = NSData.FromArray (new byte [] { 1, 2, 3 })) { + using (var sig = key.CreateSignature (SecKeyAlgorithm.RsaSignatureRaw, data, out error)) { + Assert.Null (error, "Sign/error"); + + using (var pub = key.GetPublicKey ()) { + var result = pub.VerifySignature (SecKeyAlgorithm.RsaSignatureRaw, data, sig, out error); + Assert.Null (error, "Verify/no-error"); + Assert.True (result, "Verify/true"); + + result = pub.VerifySignature (SecKeyAlgorithm.RsaSignatureRaw, data, data, out error); + Assert.NotNull (error, "Verify/error"); + Assert.False (result, "Verify/false"); + + using (var cipher = pub.CreateEncryptedData (SecKeyAlgorithm.RsaEncryptionPkcs1, data, out error)) { + Assert.Null (error, "Encrypt/error"); + + using (var plain = key.CreateDecryptedData (SecKeyAlgorithm.RsaEncryptionPkcs1, cipher, out error)) { + Assert.Null (error, "Decrypt/error"); + Assert.That (data.ToArray (), Is.EqualTo (plain.ToArray ()), "roundtrip"); + } + + Assert.Null (key.CreateDecryptedData (SecKeyAlgorithm.RsaEncryptionPkcs1, data, out error), "bad data"); + Assert.NotNull (error, "bad decrypt"); + } + } + } + + using (var sig = key.CreateSignature (SecKeyAlgorithm.EcdsaSignatureRfc4754, data, out error)) { + Assert.NotNull (error, "wrong key type"); + } + } + } + } + + [Test] + public void EC () + { + TestRuntime.AssertXcodeVersion (8, 0); + NSError error; + using (var key = SecKey.CreateRandomKey (SecKeyType.EC, 384, null, out error)) { + Assert.Null (error, "EC/error"); + using (var data = NSData.FromArray (new byte [] { 1, 2, 3 })) { + using (var sig = key.CreateSignature (SecKeyAlgorithm.EcdsaSignatureRfc4754, data, out error)) { + Assert.Null (error, "Sign/error"); + + using (var pub = key.GetPublicKey ()) { + var result = pub.VerifySignature (SecKeyAlgorithm.EcdsaSignatureRfc4754, data, sig, out error); + Assert.Null (error, "Verify/no-error"); + Assert.True (result, "Verify/true"); + + result = pub.VerifySignature (SecKeyAlgorithm.EcdsaSignatureRfc4754, data, data, out error); + Assert.NotNull (error, "Verify/error"); + Assert.False (result, "Verify/false"); + + using (var cipher = pub.CreateEncryptedData (SecKeyAlgorithm.EciesEncryptionCofactorX963Sha1AesGcm, data, out error)) { + Assert.Null (error, "Encrypt/error"); + + using (var plain = key.CreateDecryptedData (SecKeyAlgorithm.EciesEncryptionCofactorX963Sha1AesGcm, cipher, out error)) { + Assert.Null (error, "Decrypt/error"); + Assert.That (data.ToArray (), Is.EqualTo (plain.ToArray ()), "roundtrip"); + } + + Assert.Null (key.CreateDecryptedData (SecKeyAlgorithm.EciesEncryptionCofactorX963Sha1AesGcm, data, out error), "bad data"); + Assert.NotNull (error, "bad decrypt"); + } + } + } + + using (var sig = key.CreateSignature (SecKeyAlgorithm.RsaSignatureRaw, data, out error)) { + Assert.NotNull (error, "wrong key type"); + } + } + } + } + + [Test] + public void ECSecPrimeRandom () + { + TestRuntime.AssertXcodeVersion (8,0); + NSError error; + using (var key = SecKey.CreateRandomKey (SecKeyType.ECSecPrimeRandom, 384, null, out error)) { + Assert.Null (error, "ECSecPrimeRandom/error"); + + SecKeyKeyExchangeParameter p = new SecKeyKeyExchangeParameter () { + RequestedSize = 16, + SharedInfo = NSData.FromArray (new byte [] { 4, 5, 6 }) + }; + + using (var pub = key.GetPublicKey ()) + using (var ex = key.GetKeyExchangeResult (SecKeyAlgorithm.EcdhKeyExchangeStandardX963Sha512, pub, p.Dictionary, out error)) { + Assert.Null (error, "GetKeyExchangeResult/error"); + Assert.That (ex.Length, Is.EqualTo (p.RequestedSize), "GetKeyExchangeResult/result"); + } + } + } } }