MYCertificate now checks validity of self-signed certs loaded from the keychain (because the Security framework doesn't validate self-signed certs.)
authorJens Alfke <jens@mooseyard.com>
Tue Jul 21 10:13:08 2009 -0700 (2009-07-21)
changeset 27d0aadddb9c64
parent 26 d9c2a06d4e4e
child 28 54b373aa65ab
MYCertificate now checks validity of self-signed certs loaded from the keychain (because the Security framework doesn't validate self-signed certs.)
MYCertificate.m
MYCrypto.xcodeproj/project.pbxproj
     1.1 --- a/MYCertificate.m	Wed Jul 01 14:19:13 2009 -0700
     1.2 +++ b/MYCertificate.m	Tue Jul 21 10:13:08 2009 -0700
     1.3 @@ -14,6 +14,12 @@
     1.4  #import "MYErrorUtils.h"
     1.5  
     1.6  
     1.7 +@interface MYCertificate ()
     1.8 +- (BOOL) _verify;
     1.9 +@end
    1.10 +
    1.11 +
    1.12 +
    1.13  @implementation MYCertificate
    1.14  
    1.15  
    1.16 @@ -22,6 +28,11 @@
    1.17      self = [super initWithKeychainItemRef: (SecKeychainItemRef)certificateRef];
    1.18      if (self) {
    1.19          _certificateRef = certificateRef;     // superclass has already CFRetained it
    1.20 +        if (![self _verify]) {
    1.21 +            Log(@"Self-signed cert failed signature verification (%@)", self);
    1.22 +            [self release];
    1.23 +            return nil;
    1.24 +        }
    1.25      }
    1.26      return self;
    1.27  }
    1.28 @@ -54,17 +65,10 @@
    1.29      self = [self initWithCertificateRef: certificateRef];
    1.30      CFRelease(certificateRef);
    1.31      
    1.32 -    // If the cert is self-signed, verify its signature. Apple's frameworks don't do this,
    1.33 -    // even the SecTrust API; if the signature doesn't verify, they just assume it could be
    1.34 -    // signed by a different cert. Seems like a bad decision to me, so I'll add the check:
    1.35 -    MYCertificateInfo *info = self.info;
    1.36 -    if (info.isRoot) {
    1.37 -        Log(@"Verifying self-signed certificate %@ ...", self);
    1.38 -        if (![info verifySignatureWithKey: self.publicKey]) {
    1.39 -            Log(@"Self-signed cert failed signature verification (%@)", self);
    1.40 -            [self release];
    1.41 -            return nil;
    1.42 -        }
    1.43 +    if (![self _verify]) {
    1.44 +          Log(@"Self-signed cert failed signature verification (%@)", self);
    1.45 +          [self release];
    1.46 +          return nil;
    1.47      }
    1.48      
    1.49      return self;
    1.50 @@ -77,6 +81,7 @@
    1.51                                  encoding: CSSM_CERT_ENCODING_BER];
    1.52  }
    1.53  #endif
    1.54 +
    1.55  - (void) dealloc
    1.56  {
    1.57      [_info release];
    1.58 @@ -213,6 +218,15 @@
    1.59  #pragma mark TRUST/POLICY STUFF:
    1.60  
    1.61  
    1.62 +- (BOOL) _verify {
    1.63 +  // If the cert is self-signed, verify its signature. Apple's frameworks don't do this,
    1.64 +  // even the SecTrust API; if the signature doesn't verify, they just assume it could be
    1.65 +  // signed by a different cert. Seems like a bad decision to me, so I'll add the check:
    1.66 +  MYCertificateInfo *info = self.info;
    1.67 +  return !info.isRoot || [info verifySignatureWithKey: self.publicKey];
    1.68 +}  
    1.69 +
    1.70 +
    1.71  - (SecTrustResultType) evaluateTrustWithPolicy: (SecPolicyRef)policy {
    1.72      SecTrustRef trust;
    1.73      if (!check(SecTrustCreateWithCertificates((CFArrayRef)$array((id)_certificateRef), policy, &trust), 
     2.1 --- a/MYCrypto.xcodeproj/project.pbxproj	Wed Jul 01 14:19:13 2009 -0700
     2.2 +++ b/MYCrypto.xcodeproj/project.pbxproj	Tue Jul 21 10:13:08 2009 -0700
     2.3 @@ -124,7 +124,7 @@
     2.4  		27B855250FD077A6005631F9 /* MYDEREncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYDEREncoder.h; sourceTree = "<group>"; };
     2.5  		27B855260FD077A6005631F9 /* MYDEREncoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYDEREncoder.m; sourceTree = "<group>"; };
     2.6  		27CFF4B10F7E8535000B418E /* MYCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCertificate.h; sourceTree = "<group>"; };
     2.7 -		27CFF4B20F7E8535000B418E /* MYCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCertificate.m; sourceTree = "<group>"; };
     2.8 +		27CFF4B20F7E8535000B418E /* MYCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = MYCertificate.m; sourceTree = "<group>"; };
     2.9  		27CFF4B30F7E8535000B418E /* MYCryptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCryptor.h; sourceTree = "<group>"; };
    2.10  		27CFF4B40F7E8535000B418E /* MYCryptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCryptor.m; sourceTree = "<group>"; };
    2.11  		27CFF4B50F7E8535000B418E /* MYKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYKeychain.h; sourceTree = "<group>"; };
    2.12 @@ -227,8 +227,10 @@
    2.13  				27EAF0390F8B2D700091AF95 /* README.textile */,
    2.14  				27FEB3E60FBA63D200290049 /* MYCrypto.h */,
    2.15  			);
    2.16 +			indentWidth = 4;
    2.17  			name = Source;
    2.18  			sourceTree = "<group>";
    2.19 +			usesTabs = 0;
    2.20  		};
    2.21  		08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
    2.22  			isa = PBXGroup;
    2.23 @@ -257,8 +259,10 @@
    2.24  				27CFF4B30F7E8535000B418E /* MYCryptor.h */,
    2.25  				27CFF4B40F7E8535000B418E /* MYCryptor.m */,
    2.26  			);
    2.27 +			indentWidth = 4;
    2.28  			name = Encryption;
    2.29  			sourceTree = "<group>";
    2.30 +			usesTabs = 0;
    2.31  		};
    2.32  		270B881C0F8D055A00C56781 /* Internal */ = {
    2.33  			isa = PBXGroup;
    2.34 @@ -270,8 +274,10 @@
    2.35  				27CFF5400F7E9653000B418E /* MYCrypto_Debug.xcconfig */,
    2.36  				2748604D0F8D5C4C00FE617B /* MYCrypto_Release.xcconfig */,
    2.37  			);
    2.38 +			indentWidth = 4;
    2.39  			name = Internal;
    2.40  			sourceTree = "<group>";
    2.41 +			usesTabs = 0;
    2.42  		};
    2.43  		274861440F8D757600FE617B /* Certificates */ = {
    2.44  			isa = PBXGroup;
    2.45 @@ -288,8 +294,10 @@
    2.46  				27B852FC0FCF4ECB005631F9 /* MYOID.h */,
    2.47  				27B852FD0FCF4ECB005631F9 /* MYOID.m */,
    2.48  			);
    2.49 +			indentWidth = 4;
    2.50  			name = Certificates;
    2.51  			sourceTree = "<group>";
    2.52 +			usesTabs = 0;
    2.53  		};
    2.54  		27CFF4CC0F7E86E8000B418E /* MYUtilities */ = {
    2.55  			isa = PBXGroup;
    2.56 @@ -306,8 +314,10 @@
    2.57  				27CFF5750F7E999B000B418E /* MYErrorUtils.m */,
    2.58  				27CFF57C0F7EA117000B418E /* MYError_CSSMErrorDomain.strings */,
    2.59  			);
    2.60 +			indentWidth = 4;
    2.61  			name = MYUtilities;
    2.62  			sourceTree = MYUtilities;
    2.63 +			usesTabs = 0;
    2.64  		};
    2.65  		C6859EA2029092E104C91782 /* Documentation */ = {
    2.66  			isa = PBXGroup;