Factored out the name accessors of MYParsedCertificate into a new class MYCertificateName, so that both subject and issuer can be accessed. A bit of other cleanup too.
5 // Created by Jens Alfke on 3/26/09.
6 // Copyright 2009 Jens Alfke. All rights reserved.
9 #import "MYCertificate.h"
10 #import "MYCrypto_Private.h"
11 #import "MYIdentity.h"
13 #import "MYErrorUtils.h"
15 #if !MYCRYPTO_USE_IPHONE_API
18 @implementation MYCertificate
21 /** Creates a MYCertificate object for an existing Keychain certificate reference. */
22 - (id) initWithCertificateRef: (SecCertificateRef)certificateRef {
23 self = [super initWithKeychainItemRef: (SecKeychainItemRef)certificateRef];
25 _certificateRef = certificateRef; // superclass has already CFRetained it
30 + (MYCertificate*) certificateWithCertificateRef: (SecCertificateRef)certificateRef {
31 return [[[self alloc] initWithCertificateRef: certificateRef] autorelease];
34 /** Creates a MYCertificate object from exported key data, but does not add it to any keychain. */
35 - (id) initWithCertificateData: (NSData*)data
36 type: (CSSM_CERT_TYPE) type
37 encoding: (CSSM_CERT_ENCODING) encoding
40 CSSM_DATA cssmData = {.Data=(void*)data.bytes, .Length=data.length};
41 SecCertificateRef certificateRef = NULL;
42 if (!check(SecCertificateCreateFromData(&cssmData, type, encoding, &certificateRef),
43 @"SecCertificateCreateFromData")) {
47 self = [self initWithCertificateRef: certificateRef];
48 CFRelease(certificateRef);
52 - (id) initWithCertificateData: (NSData*)data {
53 return [self initWithCertificateData: data
54 type: CSSM_CERT_X_509v3
55 encoding: CSSM_CERT_ENCODING_BER];
59 - (NSString*) description {
60 return $sprintf(@"%@[%@ %@/%p]",
63 self.certificateData.my_SHA1Digest.abbreviatedHexString,
68 - (BOOL)isEqualToCertificate:(MYCertificate*)cert {
69 return [self isEqual: cert] || [self.certificateData isEqual: cert.certificateData];
73 + (MYCertificate*) preferredCertificateForName: (NSString*)name {
74 SecCertificateRef certRef = NULL;
75 if (!check(SecCertificateCopyPreference((CFStringRef)name, 0, &certRef),
76 @"SecCertificateCopyPreference"))
78 return [[[MYCertificate alloc] initWithCertificateRef: certRef] autorelease];
81 - (BOOL) setPreferredCertificateForName: (NSString*)name {
82 return check(SecCertificateSetPreference(_certificateRef, (CFStringRef)name, 0, NULL),
83 @"SecCertificateSetPreference");
87 @synthesize certificateRef=_certificateRef;
89 - (NSData*) certificateData {
91 if (!check(SecCertificateGetData(_certificateRef, &cssmData),
92 @"SecCertificateGetData"))
94 return [NSData dataWithBytes: cssmData.Data length: cssmData.Length];
97 - (MYPublicKey*) publicKey {
98 SecKeyRef keyRef = NULL;
99 if (!check(SecCertificateCopyPublicKey(_certificateRef, &keyRef),
100 @"SecCertificateCopyPublicKey") || !keyRef)
102 MYPublicKey *key = [[[MYPublicKey alloc] initWithKeyRef: keyRef] autorelease];
107 - (MYIdentity*) identity {
108 return [[[MYIdentity alloc] initWithCertificateRef: _certificateRef] autorelease];
111 - (NSString*) commonName {
112 CFStringRef name = NULL;
113 if (!check(SecCertificateCopyCommonName(_certificateRef, &name),
114 @"SecCertificateCopyCommonName") || !name)
116 return [(id)CFMakeCollectable(name) autorelease];
119 - (NSArray*) emailAddresses {
120 CFArrayRef addrs = NULL;
121 if (!check(SecCertificateCopyEmailAddresses(_certificateRef, &addrs),
122 @"SecCertificateCopyEmailAddresses") || !addrs)
124 return [(id)CFMakeCollectable(addrs) autorelease];
129 #pragma mark TRUST/POLICY STUFF:
132 + (SecPolicyRef) policyForOID: (CSSM_OID) policyOID {
133 SecPolicySearchRef search;
134 if (!check(SecPolicySearchCreate(CSSM_CERT_X_509v3, &policyOID, NULL, &search),
135 @"SecPolicySearchCreate"))
137 SecPolicyRef policy = NULL;
138 if (!check(SecPolicySearchCopyNext(search, &policy), @"SecPolicySearchCopyNext"))
144 + (SecPolicyRef) X509Policy {
145 static SecPolicyRef sX509Policy = NULL;
147 sX509Policy = [self policyForOID: CSSMOID_APPLE_X509_BASIC];
151 + (SecPolicyRef) SSLPolicy {
152 static SecPolicyRef sSSLPolicy = NULL;
154 sSSLPolicy = [self policyForOID: CSSMOID_APPLE_TP_SSL];
158 + (SecPolicyRef) SMIMEPolicy {
159 static SecPolicyRef sSMIMEPolicy = NULL;
161 sSMIMEPolicy = [self policyForOID: CSSMOID_APPLE_TP_SMIME];
166 - (CSSM_CERT_TYPE) certificateType {
167 CSSM_CERT_TYPE type = CSSM_CERT_UNKNOWN;
168 if (!check(SecCertificateGetType(_certificateRef, &type), @"SecCertificateGetType"))
169 type = CSSM_CERT_UNKNOWN;
173 - (NSArray*) trustSettings {
174 CFArrayRef settings = NULL;
175 OSStatus err = SecTrustSettingsCopyTrustSettings(_certificateRef, kSecTrustSettingsDomainUser,
177 if (err == errSecItemNotFound || !check(err,@"SecTrustSettingsCopyTrustSettings") || !settings)
179 return [(id)CFMakeCollectable(settings) autorelease];
183 - (BOOL) setUserTrust: (SecTrustUserSetting)trustSetting
185 if (trustSetting == kSecTrustResultProceed) {
186 return check(SecTrustSettingsSetTrustSettings(_certificateRef,
187 kSecTrustSettingsDomainUser, nil),
188 @"SecTrustSettingsSetTrustSettings");
189 } else if (trustSetting == kSecTrustResultDeny) {
190 OSStatus err = SecTrustSettingsRemoveTrustSettings(_certificateRef,
191 kSecTrustSettingsDomainUser);
192 return err == errSecItemNotFound || check(err, @"SecTrustSettingsRemoveTrustSettings");
201 NSString* MYPolicyGetName( SecPolicyRef policy ) {
205 SecPolicyGetOID(policy, &oid);
206 return $sprintf(@"SecPolicy[%@]", OIDAsString(oid));
209 NSString* MYTrustResultDescribe( SecTrustResultType result ) {
210 static NSString* const kTrustResultNames[kSecTrustResultOtherError+1] = {
216 @"RecoverableTrustFailure",
217 @"FatalTrustFailure",
220 if (result>=0 && result <=kSecTrustResultOtherError)
221 return kTrustResultNames[result];
223 return $sprintf(@"(Unknown trust result %i)", result);
227 NSString* MYTrustDescribe( SecTrustRef trust ) {
228 SecTrustResultType result;
229 CFArrayRef certChain=NULL;
230 CSSM_TP_APPLE_EVIDENCE_INFO* statusChain;
231 OSStatus err = SecTrustGetResult(trust, &result, &certChain, &statusChain);
234 desc = $sprintf(@"SecTrust[%p, err=%@]", trust, MYErrorName(NSOSStatusErrorDomain, err));
236 desc = $sprintf(@"SecTrust[%@, %u in chain]",
237 MYTrustResultDescribe(result),
238 CFArrayGetCount(certChain));
239 if (certChain) CFRelease(certChain);
244 // Taken from Keychain.framework
245 NSString* OIDAsString(const CSSM_OID oid) {
246 if ((NULL == oid.Data) || (0 >= oid.Length)) {
249 NSMutableString *result = [NSMutableString stringWithCapacity:(4 * oid.Length)];
252 for (i = 0; i < oid.Length; ++i) {
253 [result appendFormat:@"%s%hhu", ((0 == i) ? "" : ", "), oid.Data[i]];
263 Log(@"X.509 policy = %@", MYPolicyGetName([MYCertificate X509Policy]));
264 Log(@" SSL policy = %@", MYPolicyGetName([MYCertificate SSLPolicy]));
265 Log(@"SMIME policy = %@", MYPolicyGetName([MYCertificate SMIMEPolicy]));
266 for (MYCertificate *cert in [[MYKeychain defaultKeychain] enumerateCertificates]) {
267 NSArray *settings = cert.trustSettings;
269 Log(@"---- %@ = %@", cert, settings);
274 #endif !MYCRYPTO_USE_IPHONE_API
279 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
281 Redistribution and use in source and binary forms, with or without modification, are permitted
282 provided that the following conditions are met:
284 * Redistributions of source code must retain the above copyright notice, this list of conditions
285 and the following disclaimer.
286 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
287 and the following disclaimer in the documentation and/or other materials provided with the
290 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
291 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
292 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
293 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
294 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
295 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
296 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
297 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.