From a6dfe3305be99ac9468ab1315621441b14c96e24 Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Tue, 23 Aug 2016 10:39:27 -0400 Subject: [PATCH] [security] Add new API (up to beta 6) and unit tests A problem, that exists with the current API, is that several constants are hidden but many are needed in some dictionaries - and not all of them can be turned into _classic_ StrongDictionary. This initial PR does not solve all the (old) problems, but it does offer some useful overloads that makes the API usable for basic usages and expose the NSDictionary-based API. --- src/Security/Certificate.cs | 200 ++++++++++++++++ src/Security/Enums.cs | 14 +- src/Security/Items.cs | 38 +-- src/Security/SecAccessControl.cs | 7 +- src/Security/SecPolicy.cs | 12 +- src/Security/SecSharedCredential.cs | 2 +- src/Security/SecureTransport.cs | 19 +- src/Security/SslContext.cs | 67 +++++- src/Security/Trust.cs | 2 +- src/security.cs | 280 ++++++++++++++++++++++- tests/introspection/ApiTypoTest.cs | 5 +- tests/monotouch-test/Security/KeyTest.cs | 157 ++++++++++++- 12 files changed, 740 insertions(+), 63 deletions(-) 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"); + } + } + } } }