MYCertificate.m
changeset 9 aa5eb3fd6ebf
parent 2 8982b8fada63
child 12 e4c971be4079
     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