1.1 --- a/MYCertificate.m Tue Apr 07 10:56:58 2009 -0700
1.2 +++ b/MYCertificate.m Sun Apr 12 22:16:14 2009 -0700
1.3 @@ -8,6 +8,8 @@
1.4
1.5 #import "MYCertificate.h"
1.6 #import "MYCrypto_Private.h"
1.7 +#import "MYDigest.h"
1.8 +#import "MYErrorUtils.h"
1.9
1.10 #if !MYCRYPTO_USE_IPHONE_API
1.11
1.12 @@ -24,6 +26,10 @@
1.13 return self;
1.14 }
1.15
1.16 ++ (MYCertificate*) certificateWithCertificateRef: (SecCertificateRef)certificateRef {
1.17 + return [[[self alloc] initWithCertificateRef: certificateRef] autorelease];
1.18 +}
1.19 +
1.20 /** Creates a MYCertificate object from exported key data, but does not add it to any keychain. */
1.21 - (id) initWithCertificateData: (NSData*)data
1.22 type: (CSSM_CERT_TYPE) type
1.23 @@ -48,6 +54,21 @@
1.24 encoding: CSSM_CERT_ENCODING_BER];
1.25 }
1.26
1.27 +
1.28 +- (NSString*) description {
1.29 + return $sprintf(@"%@[%@ %@/%p]",
1.30 + [self class],
1.31 + self.commonName,
1.32 + self.certificateData.my_SHA1Digest.abbreviatedHexString,
1.33 + _certificateRef);
1.34 +}
1.35 +
1.36 +
1.37 +- (BOOL)isEqualToCertificate:(MYCertificate*)cert {
1.38 + return [self isEqual: cert] || [self.certificateData isEqual: cert.certificateData];
1.39 +}
1.40 +
1.41 +
1.42 + (MYCertificate*) preferredCertificateForName: (NSString*)name {
1.43 SecCertificateRef certRef = NULL;
1.44 if (!check(SecCertificateCopyPreference((CFStringRef)name, 0, &certRef),
1.45 @@ -61,6 +82,7 @@
1.46 @"SecCertificateSetPreference");
1.47 }
1.48
1.49 +
1.50 @synthesize certificateRef=_certificateRef;
1.51
1.52 - (NSData*) certificateData {
1.53 @@ -98,7 +120,133 @@
1.54 }
1.55
1.56
1.57 +#pragma mark -
1.58 +#pragma mark TRUST/POLICY STUFF:
1.59 +
1.60 +
1.61 ++ (SecPolicyRef) policyForOID: (CSSM_OID) policyOID {
1.62 + SecPolicySearchRef search;
1.63 + if (!check(SecPolicySearchCreate(CSSM_CERT_X_509v3, &policyOID, NULL, &search),
1.64 + @"SecPolicySearchCreate"))
1.65 + return nil;
1.66 + SecPolicyRef policy = NULL;
1.67 + if (!check(SecPolicySearchCopyNext(search, &policy), @"SecPolicySearchCopyNext"))
1.68 + policy = NULL;
1.69 + CFRelease(search);
1.70 + return policy;
1.71 +}
1.72 +
1.73 ++ (SecPolicyRef) X509Policy {
1.74 + static SecPolicyRef sX509Policy = NULL;
1.75 + if (!sX509Policy)
1.76 + sX509Policy = [self policyForOID: CSSMOID_APPLE_X509_BASIC];
1.77 + return sX509Policy;
1.78 +}
1.79 +
1.80 ++ (SecPolicyRef) SSLPolicy {
1.81 + static SecPolicyRef sSSLPolicy = NULL;
1.82 + if (!sSSLPolicy)
1.83 + sSSLPolicy = [self policyForOID: CSSMOID_APPLE_TP_SSL];
1.84 + return sSSLPolicy;
1.85 +}
1.86 +
1.87 ++ (SecPolicyRef) SMIMEPolicy {
1.88 + static SecPolicyRef sSMIMEPolicy = NULL;
1.89 + if (!sSMIMEPolicy)
1.90 + sSMIMEPolicy = [self policyForOID: CSSMOID_APPLE_TP_SMIME];
1.91 + return sSMIMEPolicy;
1.92 +}
1.93 +
1.94 +
1.95 +- (CSSM_CERT_TYPE) certificateType {
1.96 + CSSM_CERT_TYPE type = CSSM_CERT_UNKNOWN;
1.97 + if (!check(SecCertificateGetType(_certificateRef, &type), @"SecCertificateGetType"))
1.98 + type = CSSM_CERT_UNKNOWN;
1.99 + return type;
1.100 +}
1.101 +
1.102 +- (NSArray*) trustSettings {
1.103 + CFArrayRef settings = NULL;
1.104 + OSStatus err = SecTrustSettingsCopyTrustSettings(_certificateRef, kSecTrustSettingsDomainUser,
1.105 + &settings);
1.106 + if (err == errSecItemNotFound || !check(err,@"SecTrustSettingsCopyTrustSettings") || !settings)
1.107 + return nil;
1.108 + return [(id)CFMakeCollectable(settings) autorelease];
1.109 +}
1.110 +
1.111 +
1.112 +- (BOOL) setUserTrust: (SecTrustUserSetting)trustSetting
1.113 +{
1.114 + if (trustSetting == kSecTrustResultProceed) {
1.115 + return check(SecTrustSettingsSetTrustSettings(_certificateRef,
1.116 + kSecTrustSettingsDomainUser, nil),
1.117 + @"SecTrustSettingsSetTrustSettings");
1.118 + } else if (trustSetting == kSecTrustResultDeny) {
1.119 + OSStatus err = SecTrustSettingsRemoveTrustSettings(_certificateRef,
1.120 + kSecTrustSettingsDomainUser);
1.121 + return err == errSecItemNotFound || check(err, @"SecTrustSettingsRemoveTrustSettings");
1.122 + } else
1.123 + return paramErr;
1.124 +}
1.125 +
1.126 +
1.127 @end
1.128
1.129
1.130 +NSString* MYPolicyGetName( SecPolicyRef policy ) {
1.131 + if (!policy)
1.132 + return @"(null)";
1.133 + CSSM_OID oid = {};
1.134 + SecPolicyGetOID(policy, &oid);
1.135 + return $sprintf(@"SecPolicy[%@]", OIDAsString(oid));
1.136 +}
1.137 +
1.138 +NSString* MYTrustResultDescribe( SecTrustResultType result ) {
1.139 + static NSString* const kTrustResultNames[kSecTrustResultOtherError+1] = {
1.140 + @"Invalid",
1.141 + @"Proceed",
1.142 + @"Confirm",
1.143 + @"Deny",
1.144 + @"Unspecified",
1.145 + @"RecoverableTrustFailure",
1.146 + @"FatalTrustFailure",
1.147 + @"OtherError"
1.148 + };
1.149 + if (result>=0 && result <=kSecTrustResultOtherError)
1.150 + return kTrustResultNames[result];
1.151 + else
1.152 + return $sprintf(@"(Unknown trust result %i)", result);
1.153 +}
1.154 +
1.155 +
1.156 +NSString* MYTrustDescribe( SecTrustRef trust ) {
1.157 + SecTrustResultType result;
1.158 + CFArrayRef certChain=NULL;
1.159 + CSSM_TP_APPLE_EVIDENCE_INFO* statusChain;
1.160 + OSStatus err = SecTrustGetResult(trust, &result, &certChain, &statusChain);
1.161 + NSString *desc;
1.162 + if (err)
1.163 + desc = $sprintf(@"SecTrust[%p, err=%@]", trust, MYErrorName(NSOSStatusErrorDomain, err));
1.164 + else
1.165 + desc = $sprintf(@"SecTrust[%@, %u in chain]",
1.166 + MYTrustResultDescribe(result),
1.167 + CFArrayGetCount(certChain));
1.168 + if (certChain) CFRelease(certChain);
1.169 + return desc;
1.170 +}
1.171 +
1.172 +
1.173 +
1.174 +TestCase(Trust) {
1.175 + Log(@"X.509 policy = %@", MYPolicyGetName([MYCertificate X509Policy]));
1.176 + Log(@" SSL policy = %@", MYPolicyGetName([MYCertificate SSLPolicy]));
1.177 + Log(@"SMIME policy = %@", MYPolicyGetName([MYCertificate SMIMEPolicy]));
1.178 + for (MYCertificate *cert in [[MYKeychain defaultKeychain] enumerateCertificates]) {
1.179 + NSArray *settings = cert.trustSettings;
1.180 + if (settings)
1.181 + Log(@"---- %@ = %@", cert, settings);
1.182 + }
1.183 +}
1.184 +
1.185 +
1.186 #endif !MYCRYPTO_USE_IPHONE_API