A snapshot taken during the long, agonizing crawl toward getting everything running on iPhone.
1.1 --- a/MYCertificate-iPhone.m Sat Jun 06 15:36:35 2009 -0700
1.2 +++ b/MYCertificate-iPhone.m Sun Jun 07 21:53:56 2009 -0700
1.3 @@ -97,6 +97,10 @@
1.4 return name ?[(id)CFMakeCollectable(name) autorelease] :nil;
1.5 }
1.6
1.7 +- (NSArray*) emailAddresses {
1.8 + NSString *email = self.info.subject.emailAddress;
1.9 + return email ?$array(email) :nil;
1.10 +}
1.11
1.12 @end
1.13
2.1 --- a/MYCertificate.h Sat Jun 06 15:36:35 2009 -0700
2.2 +++ b/MYCertificate.h Sun Jun 07 21:53:56 2009 -0700
2.3 @@ -52,6 +52,9 @@
2.4 /** The common name of the subject (owner) of the certificate. */
2.5 @property (readonly) NSString *commonName;
2.6
2.7 +/** The list (if any) of the subject's email addresses. */
2.8 +@property (readonly) NSArray *emailAddresses;
2.9 +
2.10
2.11 /** @name Mac-Only
2.12 * Functionality not available on iPhone.
2.13 @@ -64,9 +67,6 @@
2.14 type: (CSSM_CERT_TYPE) type
2.15 encoding: (CSSM_CERT_ENCODING) encoding;
2.16
2.17 -/** The list (if any) of the subject's email addresses. */
2.18 -@property (readonly) NSArray *emailAddresses;
2.19 -
2.20 /** Finds the current 'preferred' certificate for the given name string. */
2.21 + (MYCertificate*) preferredCertificateForName: (NSString*)name;
2.22
3.1 --- a/MYCertificateInfo.m Sat Jun 06 15:36:35 2009 -0700
3.2 +++ b/MYCertificateInfo.m Sun Jun 07 21:53:56 2009 -0700
3.3 @@ -179,8 +179,18 @@
3.4 [MYBitString bitStringWithData: publicKey.keyData] ) ) );
3.5 self = [super initWithRoot: root];
3.6 [version release];
3.7 + if (self) {
3.8 + _publicKey = publicKey.retain;
3.9 + }
3.10 return self;
3.11 }
3.12 +
3.13 +- (void) dealloc
3.14 +{
3.15 + [_publicKey release];
3.16 + [super dealloc];
3.17 +}
3.18 +
3.19
3.20 - (NSDate*) validFrom {return [super validFrom];}
3.21 - (NSDate*) validTo {return [super validTo];}
3.22 @@ -244,11 +254,14 @@
3.23 - (MYIdentity*) createSelfSignedIdentityWithPrivateKey: (MYPrivateKey*)privateKey
3.24 error: (NSError**)outError
3.25 {
3.26 + Assert(privateKey.keychain!=nil);
3.27 NSData *certData = [self selfSignWithPrivateKey: privateKey error: outError];
3.28 if (!certData)
3.29 return nil;
3.30 MYCertificate *cert = [privateKey.keychain importCertificate: certData];
3.31 Assert(cert!=nil);
3.32 + Assert(cert.keychain!=nil);
3.33 + AssertEqual(cert.publicKey.keyData, _publicKey.keyData);
3.34 MYIdentity *identity = cert.identity;
3.35 Assert(identity!=nil);
3.36 return identity;
3.37 @@ -329,10 +342,9 @@
3.38 #if DEBUG
3.39
3.40
3.41 -static MYCertificateInfo* testCert(NSString *filename, BOOL selfSigned) {
3.42 - Log(@"--- Creating MYCertificateInfo from %@", filename);
3.43 - NSData *certData = [NSData dataWithContentsOfFile: filename];
3.44 +static MYCertificateInfo* testCertData(NSData *certData, BOOL selfSigned) {
3.45 //Log(@"Cert Data =\n%@", certData);
3.46 + CAssert(certData!=nil);
3.47 NSError *error = nil;
3.48 MYCertificateInfo *pcert = [[MYCertificateInfo alloc] initWithCertificateData: certData
3.49 error: &error];
3.50 @@ -359,10 +371,21 @@
3.51 return pcert;
3.52 }
3.53
3.54 +static MYCertificateInfo* testCert(NSString *filename, BOOL selfSigned) {
3.55 +#if TARGET_OS_IPHONE
3.56 + filename = [[NSBundle mainBundle] pathForResource: filename ofType: @"cer"];
3.57 +#else
3.58 + filename = [[@"../../Tests/" stringByAppendingPathComponent: filename]
3.59 + stringByAppendingPathExtension: @"cer"];
3.60 +#endif
3.61 + Log(@"--- Creating MYCertificateInfo from %@", filename);
3.62 + return testCertData([NSData dataWithContentsOfFile: filename], selfSigned);
3.63 +}
3.64 +
3.65
3.66 TestCase(ParsedCert) {
3.67 - testCert(@"../../Tests/selfsigned.cer", YES);
3.68 - testCert(@"../../Tests/iphonedev.cer", NO);
3.69 + testCert(@"selfsigned", YES);
3.70 + testCert(@"iphonedev", NO);
3.71 }
3.72
3.73
3.74 @@ -395,8 +418,10 @@
3.75 CAssert(certData);
3.76 CAssertNil(error);
3.77 CAssert(certData);
3.78 +#if !TARGET_OS_IPHONE
3.79 [certData writeToFile: @"../../Tests/generated.cer" atomically: YES];
3.80 - MYCertificateInfo *pcert2 = testCert(@"../../Tests/generated.cer", YES);
3.81 +#endif
3.82 + MYCertificateInfo *pcert2 = testCertData(certData, YES);
3.83
3.84 Log(@"Verifying Info...");
3.85 MYCertificateName *subject2 = pcert2.subject;
4.1 --- a/MYCrypto-iPhone.xcodeproj/project.pbxproj Sat Jun 06 15:36:35 2009 -0700
4.2 +++ b/MYCrypto-iPhone.xcodeproj/project.pbxproj Sun Jun 07 21:53:56 2009 -0700
4.3 @@ -25,6 +25,8 @@
4.4 276FB3190F856AA700CB326E /* MYPublicKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB3180F856AA700CB326E /* MYPublicKey.m */; };
4.5 276FB33B0F856ACB00CB326E /* MYKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB33A0F856ACB00CB326E /* MYKeychain.m */; };
4.6 276FB34B0F856CA400CB326E /* MYCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FB34A0F856CA400CB326E /* MYCertificate.m */; };
4.7 + 27958CA30FDB5F8F00095275 /* iphonedev.cer in Resources */ = {isa = PBXBuildFile; fileRef = 27958CA10FDB5F8F00095275 /* iphonedev.cer */; };
4.8 + 27958CA40FDB5F8F00095275 /* selfsigned.cer in Resources */ = {isa = PBXBuildFile; fileRef = 27958CA20FDB5F8F00095275 /* selfsigned.cer */; };
4.9 27A430120F87C6C10063D362 /* MYKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E823110F81D56E0019BE60 /* MYKey.m */; };
4.10 27A430140F87C6D50063D362 /* MYSymmetricKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A430130F87C6D50063D362 /* MYSymmetricKey.m */; };
4.11 27CD85DD0FDB1A82006BCB47 /* MYCertificateInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CD85DC0FDB1A82006BCB47 /* MYCertificateInfo.m */; };
4.12 @@ -70,6 +72,8 @@
4.13 276FB3180F856AA700CB326E /* MYPublicKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYPublicKey.m; sourceTree = "<group>"; };
4.14 276FB33A0F856ACB00CB326E /* MYKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYKeychain.m; sourceTree = "<group>"; };
4.15 276FB34A0F856CA400CB326E /* MYCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCertificate.m; sourceTree = "<group>"; };
4.16 + 27958CA10FDB5F8F00095275 /* iphonedev.cer */ = {isa = PBXFileReference; lastKnownFileType = file; name = iphonedev.cer; path = Tests/iphonedev.cer; sourceTree = "<group>"; };
4.17 + 27958CA20FDB5F8F00095275 /* selfsigned.cer */ = {isa = PBXFileReference; lastKnownFileType = file; name = selfsigned.cer; path = Tests/selfsigned.cer; sourceTree = "<group>"; };
4.18 27A430130F87C6D50063D362 /* MYSymmetricKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYSymmetricKey.m; sourceTree = "<group>"; };
4.19 27A430150F87C6DB0063D362 /* MYSymmetricKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYSymmetricKey.h; sourceTree = "<group>"; };
4.20 27AAD9710F8927DB0064DD7C /* MYCryptoConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCryptoConfig.h; sourceTree = "<group>"; };
4.21 @@ -155,6 +159,8 @@
4.22 275D9FEA0FD8795300D85A86 /* MYDEREncoder.m */,
4.23 275D9FEB0FD8795300D85A86 /* MYOID.h */,
4.24 275D9FEC0FD8795300D85A86 /* MYOID.m */,
4.25 + 27958CA10FDB5F8F00095275 /* iphonedev.cer */,
4.26 + 27958CA20FDB5F8F00095275 /* selfsigned.cer */,
4.27 );
4.28 name = Certificates;
4.29 sourceTree = "<group>";
4.30 @@ -291,6 +297,8 @@
4.31 27E823290F81D56E0019BE60 /* MYCrypto.xcconfig in Resources */,
4.32 27E8232A0F81D56E0019BE60 /* MYCrypto_Debug.xcconfig in Resources */,
4.33 27E8233C0F81D5760019BE60 /* MYError_CSSMErrorDomain.strings in Resources */,
4.34 + 27958CA30FDB5F8F00095275 /* iphonedev.cer in Resources */,
4.35 + 27958CA40FDB5F8F00095275 /* selfsigned.cer in Resources */,
4.36 );
4.37 runOnlyForDeploymentPostprocessing = 0;
4.38 };
5.1 --- a/MYCryptoTest.m Sat Jun 06 15:36:35 2009 -0700
5.2 +++ b/MYCryptoTest.m Sun Jun 07 21:53:56 2009 -0700
5.3 @@ -43,23 +43,44 @@
5.4 }
5.5
5.6
5.7 -TestCase(EnumerateKeys) {
5.8 +TestCase(Enumerate) {
5.9 + RequireTestCase(EnumeratePublicKeys);
5.10 + RequireTestCase(EnumeratePrivateKeys);
5.11 + RequireTestCase(EnumerateSymmetricKeys);
5.12 + RequireTestCase(EnumerateCerts);
5.13 + RequireTestCase(EnumerateIdentities);
5.14 +}
5.15 +
5.16 +
5.17 +TestCase(EnumeratePublicKeys) {
5.18 RequireTestCase(MYKeychain);
5.19 NSEnumerator *e = [[MYKeychain allKeychains] enumeratePublicKeys];
5.20 Log(@"Public Key Enumerator = %@", e);
5.21 CAssert(e);
5.22 for (MYPublicKey *key in e) {
5.23 - Log(@"Found %@ -- name=%@", key, key.name);
5.24 + Log(@"Trying public key %@", key.keyRef);
5.25 + @try{
5.26 + Log(@"Found %@ -- name=%@", key, key.name);
5.27 + }@catch (NSException *x) {
5.28 + Warn(@"Caught %@",x); //TEMP
5.29 + }
5.30 }
5.31 -
5.32 - e = [[MYKeychain allKeychains] enumeratePrivateKeys];
5.33 +}
5.34 +
5.35 +TestCase(EnumeratePrivateKeys) {
5.36 + RequireTestCase(MYKeychain);
5.37 + NSEnumerator *e = [[MYKeychain allKeychains] enumeratePrivateKeys];
5.38 Log(@"Key-Pair Enumerator = %@", e);
5.39 CAssert(e);
5.40 for (MYPrivateKey *key in e) {
5.41 - Log(@"Found %@ -- name=%@", key, key.name);
5.42 + Log(@"Found %@ -- name=%@ --> %@", key, key.name, key.publicKey);
5.43 + CAssert(key.publicKey);
5.44 }
5.45 -
5.46 - e = [[MYKeychain allKeychains] enumerateSymmetricKeys];
5.47 +}
5.48 +
5.49 +TestCase(EnumerateSymmetricKeys) {
5.50 + RequireTestCase(MYKeychain);
5.51 + NSEnumerator *e = [[MYKeychain allKeychains] enumerateSymmetricKeys];
5.52 Log(@"Symmetric Key Enumerator = %@", e);
5.53 CAssert(e);
5.54 for (MYSymmetricKey *key in e) {
5.55 @@ -74,7 +95,8 @@
5.56 Log(@"Enumerator = %@", e);
5.57 CAssert(e);
5.58 for (MYCertificate *cert in e) {
5.59 - //Log(@"Found %@ -- name=%@, email=%@", cert, cert.commonName, cert.emailAddresses);
5.60 + Log(@"Found %@ -- name=%@, email=%@", cert, cert.commonName, cert.emailAddresses);
5.61 + CAssert(cert.publicKey);
5.62 }
5.63 }
5.64
5.65 @@ -112,7 +134,7 @@
5.66 else
5.67 key = [MYSymmetricKey generateSymmetricKeyOfSize: sizeInBits algorithm: algorithm];
5.68 Log(@"Created %@", key);
5.69 - CAssert(key);
5.70 + CAssert(key);
5.71 CAssertEq(key.algorithm, algorithm);
5.72 CAssertEq(key.keySizeInBits, sizeInBits);
5.73 #if !TARGET_OS_IPHONE
6.1 --- a/MYCrypto_Private.h Sat Jun 06 15:36:35 2009 -0700
6.2 +++ b/MYCrypto_Private.h Sun Jun 07 21:53:56 2009 -0700
6.3 @@ -53,10 +53,12 @@
6.4 - (id) initWithKeyData: (NSData*)data;
6.5 - (id) _initWithKeyData: (NSData*)data
6.6 forKeychain: (SecKeychainRef)keychain;
6.7 -@property (readonly) SecExternalItemType keyType;
6.8 +@property (readonly) SecExternalItemType keyClass, keyType;
6.9 @property (readonly) MYSHA1Digest* _keyDigest;
6.10 - (NSData*) _crypt: (NSData *)data operation: (BOOL) op; // YES to encrypt, NO to decrypt
6.11 -#if !MYCRYPTO_USE_IPHONE_API
6.12 +#if MYCRYPTO_USE_IPHONE_API
6.13 ++ (SecKeyRef) _addKeyWithInfo: (NSMutableDictionary*)info;
6.14 +#else
6.15 @property (readonly) const CSSM_KEY* cssmKey;
6.16 @property (readonly) const CSSM_CSP_HANDLE cssmCSPHandle;
6.17 - (CSSM_CC_HANDLE) _createSignatureContext: (CSSM_ALGORITHMS)algorithm;
7.1 --- a/MYDigest.h Sat Jun 06 15:36:35 2009 -0700
7.2 +++ b/MYDigest.h Sun Jun 07 21:53:56 2009 -0700
7.3 @@ -24,16 +24,16 @@
7.4 - (id) initWithRawDigest: (const void*)rawDigest length: (size_t)length;
7.5
7.6 /** Wraps an existing digest, stored in an NSData object, in a MYDigest object. */
7.7 -+ (MYDigest*) digestFromDigestData: (NSData*)digestData;
7.8 ++ (id) digestFromDigestData: (NSData*)digestData;
7.9
7.10 /** Wraps an existing digest, expressed as a hex string, in a MYDigest object. */
7.11 -+ (MYDigest*) digestFromHexString: (NSString*)hexString;
7.12 ++ (id) digestFromHexString: (NSString*)hexString;
7.13
7.14 /** Computes a cryptographic digest of the given data. */
7.15 -+ (MYDigest*) digestOfData: (NSData*)data;
7.16 ++ (id) digestOfData: (NSData*)data;
7.17
7.18 /** Computes a cryptographic digest of the given data. */
7.19 -+ (MYDigest*) digestOfBytes: (const void*)bytes length: (size_t)length;
7.20 ++ (id) digestOfBytes: (const void*)bytes length: (size_t)length;
7.21
7.22 /** Returns the digest as an NSData object. */
7.23 @property (readonly) NSData *asData;
8.1 --- a/MYDigest.m Sat Jun 06 15:36:35 2009 -0700
8.2 +++ b/MYDigest.m Sun Jun 07 21:53:56 2009 -0700
8.3 @@ -79,11 +79,11 @@
8.4 }
8.5
8.6
8.7 -+ (MYDigest*) digestFromDigestData: (NSData*)digestData {
8.8 ++ (id) digestFromDigestData: (NSData*)digestData {
8.9 return [[[self alloc] initWithRawDigest: digestData.bytes length: digestData.length] autorelease];
8.10 }
8.11
8.12 -+ (MYDigest*) digestFromHexString: (NSString*)hexString
8.13 ++ (id) digestFromHexString: (NSString*)hexString
8.14 {
8.15 const char *cStr = [hexString UTF8String];
8.16 const size_t length = [self length];
8.17 @@ -98,10 +98,11 @@
8.18 return [[[self alloc] initWithRawDigest: &digest length: length] autorelease];
8.19 }
8.20
8.21 -+ (MYDigest*) digestOfData: (NSData*)data {
8.22 ++ (id) digestOfData: (NSData*)data {
8.23 return [self digestOfBytes: data.bytes length: data.length];
8.24 }
8.25 -+ (MYDigest*) digestOfBytes: (const void*)bytes length: (size_t)length {
8.26 +
8.27 ++ (id) digestOfBytes: (const void*)bytes length: (size_t)length {
8.28 const size_t digestLength = [self length];
8.29 uint8_t digest[digestLength];
8.30 [self computeDigest: digest ofBytes: bytes length: length];
9.1 --- a/MYIdentity.m Sat Jun 06 15:36:35 2009 -0700
9.2 +++ b/MYIdentity.m Sun Jun 07 21:53:56 2009 -0700
9.3 @@ -35,19 +35,21 @@
9.4 }
9.5
9.6
9.7 -#if !TARGET_OS_IPHONE
9.8 - (id) initWithCertificateRef: (SecCertificateRef)certificateRef {
9.9 self = [super initWithCertificateRef: certificateRef];
9.10 if (self) {
9.11 +#if !MYCRYPTO_USE_IPHONE_API
9.12 if (!check(SecIdentityCreateWithCertificate(NULL, certificateRef, &_identityRef),
9.13 @"SecIdentityCreateWithCertificate")) {
9.14 [self release];
9.15 return nil;
9.16 }
9.17 +#else
9.18 + Assert(NO,@"-[MYIdentity initWithCertificateRef] isn't implemented for iPhone yet!");//FIX
9.19 +#endif
9.20 }
9.21 return self;
9.22 }
9.23 -#endif
9.24
9.25 - (void) dealloc
9.26 {
9.27 @@ -69,7 +71,7 @@
9.28 if (!check(SecIdentityCopyPrivateKey(_identityRef, &keyRef), @"SecIdentityCopyPrivateKey"))
9.29 return NULL;
9.30 MYPrivateKey *privateKey = [[MYPrivateKey alloc] _initWithKeyRef: keyRef
9.31 - publicKey: self.publicKey];
9.32 + publicKey: self.publicKey];
9.33 CFRelease(keyRef);
9.34 return [privateKey autorelease];
9.35 }
10.1 --- a/MYKey-iPhone.m Sat Jun 06 15:36:35 2009 -0700
10.2 +++ b/MYKey-iPhone.m Sun Jun 07 21:53:56 2009 -0700
10.3 @@ -19,6 +19,45 @@
10.4 @implementation MYKey
10.5
10.6
10.7 ++ (SecKeyRef) _addKeyWithInfo: (NSMutableDictionary*)info {
10.8 + if (![info objectForKey: (id)kSecAttrApplicationTag]) {
10.9 + // Every keychain item has to have a unique tag, apparently, or you'll get spurious
10.10 + // duplicate-item errors. If none was given, make up a random one:
10.11 + UInt8 tag[16];
10.12 + Assert(check(SecRandomCopyBytes(kSecRandomDefault, sizeof(tag), tag), @"SecRandomCopyBytes"));
10.13 + [info setObject: [NSData dataWithBytes: tag length: sizeof(tag)]
10.14 + forKey: (id)kSecAttrApplicationTag];
10.15 + }
10.16 + CFDataRef keyPersistentRef;
10.17 + SecKeyRef key;
10.18 + OSStatus err = SecItemAdd((CFDictionaryRef)info, (CFTypeRef*)&keyPersistentRef);
10.19 + if (err==errSecDuplicateItem) {
10.20 + // it's already in the keychain -- get a reference to it:
10.21 + [info removeObjectForKey: (id)kSecReturnPersistentRef];
10.22 + [info setObject: $true forKey: (id)kSecReturnRef];
10.23 + if (check(SecItemCopyMatching((CFDictionaryRef)info, (CFTypeRef *)&key),
10.24 + @"SecItemCopyMatching"))
10.25 + return key;
10.26 + } else if (check(err, @"SecItemAdd")) {
10.27 + // It was added
10.28 + if ([[info objectForKey: (id)kSecReturnPersistentRef] boolValue]) {
10.29 + // now get its SecKeyRef:
10.30 + info = $mdict({(id)kSecValuePersistentRef, (id)keyPersistentRef},
10.31 + {(id)kSecReturnRef, $true});
10.32 + err = SecItemCopyMatching((CFDictionaryRef)info, (CFTypeRef *)&key);
10.33 + CFRelease(keyPersistentRef);
10.34 + if (check(err,@"SecItemCopyMatching")) {
10.35 + Assert(key!=nil);
10.36 + return key;
10.37 + }
10.38 + } else {
10.39 + return (SecKeyRef)keyPersistentRef;
10.40 + }
10.41 + }
10.42 + return NULL;
10.43 +}
10.44 +
10.45 +
10.46 - (id) initWithKeyRef: (SecKeyRef)key {
10.47 return [super initWithKeychainItemRef: (SecKeychainItemRef)key];
10.48 }
10.49 @@ -27,45 +66,65 @@
10.50 - (id) _initWithKeyData: (NSData*)data
10.51 forKeychain: (SecKeychainRef)keychain
10.52 {
10.53 - NSDictionary *info = $dict( {(id)kSecClass, (id)kSecClassKey},
10.54 - {(id)kSecAttrKeyClass, (id)self.keyType},
10.55 - {(id)kSecValueData, data},
10.56 - {(id)kSecAttrIsPermanent, $object(keychain!=nil)},
10.57 - {(id)kSecReturnRef, $true} );
10.58 - SecKeyRef key;
10.59 - if (!check(SecItemAdd((CFDictionaryRef)info, (CFTypeRef*)&key), @"SecItemAdd"))
10.60 + NSMutableDictionary *info = $mdict({(id)kSecClass, (id)kSecClassKey},
10.61 + {(id)kSecAttrKeyType, (id)self.keyType},
10.62 + {(id)kSecValueData, data},
10.63 + {(id)kSecAttrIsPermanent, (keychain ?$true :$false)},
10.64 + {(id)kSecReturnPersistentRef, $true} );
10.65 + SecKeyRef key = [[self class] _addKeyWithInfo: info];
10.66 + if (!key) {
10.67 + [self release];
10.68 return nil;
10.69 - else
10.70 - return [self initWithKeyRef: (SecKeyRef)key];
10.71 + }
10.72 + self = [self initWithKeyRef: (SecKeyRef)key];
10.73 + if (self) {
10.74 + if (!keychain)
10.75 + _keyData = [data copy];
10.76 + }
10.77 + return self;
10.78 }
10.79
10.80 - (id) initWithKeyData: (NSData*)data {
10.81 return [self _initWithKeyData: data forKeychain: nil];
10.82 }
10.83
10.84 +- (void) dealloc
10.85 +{
10.86 + [_keyData release];
10.87 + [super dealloc];
10.88 +}
10.89
10.90 -- (SecExternalItemType) keyType {
10.91 +
10.92 +- (SecExternalItemType) keyClass {
10.93 AssertAbstractMethod();
10.94 }
10.95
10.96 +- (SecExternalItemType) keyType {
10.97 + return NULL;
10.98 +}
10.99
10.100 - (NSData*) keyData {
10.101 - NSDictionary *info = $dict( {(id)kSecClass, (id)kSecClassKey},
10.102 - {(id)kSecAttrKeyClass, (id)self.keyType},
10.103 - {(id)kSecMatchItemList, $array((id)self.keyRef)},
10.104 + if (_keyData)
10.105 + return _keyData;
10.106 +
10.107 + NSDictionary *info = $dict( {(id)kSecValueRef, (id)self.keyRef},
10.108 {(id)kSecReturnData, $true} );
10.109 CFDataRef data;
10.110 if (!check(SecItemCopyMatching((CFDictionaryRef)info, (CFTypeRef*)&data), @"SecItemCopyMatching"))
10.111 return nil;
10.112 - else
10.113 + else {
10.114 + Assert(data!=NULL);
10.115 return [(id)CFMakeCollectable(data) autorelease];
10.116 -
10.117 + }
10.118 // The format of this data is not documented. There's been some reverse-engineering:
10.119 // https://devforums.apple.com/message/32089#32089
10.120 // Apparently it is a DER-formatted sequence of a modulus followed by an exponent.
10.121 // This can be converted to OpenSSL format by wrapping it in some additional DER goop.
10.122 }
10.123
10.124 +- (MYSHA1Digest*) _keyDigest {
10.125 + return [self.keyData my_SHA1Digest];
10.126 +}
10.127
10.128 - (SecKeyRef) keyRef {
10.129 return (SecKeyRef) self.keychainItemRef;
10.130 @@ -73,13 +132,12 @@
10.131
10.132
10.133 - (id) _attribute: (CFTypeRef)attribute {
10.134 - NSDictionary *info = $dict( {(id)kSecClass, (id)kSecClassKey},
10.135 - {(id)kSecAttrKeyClass, (id)self.keyType},
10.136 - {(id)kSecMatchItemList, $array((id)self.keyRef)},
10.137 - {(id)kSecReturnAttributes, $true} );
10.138 + NSDictionary *info = $dict({(id)kSecValueRef, (id)self.keyRef},
10.139 + {(id)kSecReturnAttributes, $true});
10.140 CFDictionaryRef attrs = NULL;
10.141 if (!check(SecItemCopyMatching((CFDictionaryRef)info, (CFTypeRef*)&attrs), @"SecItemCopyMatching"))
10.142 return nil;
10.143 + Log(@"_attribute: %@ of %@ %p", attribute, [self class], self.keyRef);//TEMP
10.144 CFTypeRef rawValue = CFDictionaryGetValue(attrs,attribute);
10.145 id value = rawValue ?[[(id)CFMakeCollectable(rawValue) retain] autorelease] :nil;
10.146 CFRelease(attrs);
10.147 @@ -90,7 +148,7 @@
10.148 if (!value)
10.149 value = (id)[NSNull null];
10.150 NSDictionary *query = $dict( {(id)kSecClass, (id)kSecClassKey},
10.151 - {(id)kSecAttrKeyClass, (id)self.keyType},
10.152 + {(id)kSecAttrKeyClass, (id)self.keyClass},
10.153 {(id)kSecMatchItemList, self._itemList} );
10.154 NSDictionary *attrs = $dict( {(id)attribute, value} );
10.155 return check(SecItemUpdate((CFDictionaryRef)query, (CFDictionaryRef)attrs), @"SecItemUpdate");
11.1 --- a/MYKey.h Sat Jun 06 15:36:35 2009 -0700
11.2 +++ b/MYKey.h Sun Jun 07 21:53:56 2009 -0700
11.3 @@ -28,7 +28,9 @@
11.4 /** Abstract superclass for keys.
11.5 Concrete subclasses are MYSymmetricKey and MYPublicKey. */
11.6 @interface MYKey : MYKeychainItem
11.7 -{ }
11.8 +{
11.9 + NSData *_keyData;
11.10 +}
11.11
11.12 /** Creates a key from encoded data (but does not add it to any keychain.) */
11.13 - (id) initWithKeyData: (NSData*)data;
12.1 --- a/MYKey.m Sat Jun 06 15:36:35 2009 -0700
12.2 +++ b/MYKey.m Sun Jun 07 21:53:56 2009 -0700
12.3 @@ -26,7 +26,7 @@
12.4 forKeychain: (SecKeychainRef)keychain {
12.5 Assert(keyData!=nil);
12.6 SecKeyImportExportParameters params = {};
12.7 - SecKeyRef key = importKey(keyData, self.keyType, keychain, ¶ms);
12.8 + SecKeyRef key = importKey(keyData, self.keyClass, keychain, ¶ms);
12.9 if (!key) {
12.10 [self release];
12.11 return nil;
12.12 @@ -45,10 +45,15 @@
12.13 return $sprintf(@"%@[%@ /%p]", [self class], (self.name ?:@""), self.keychainItemRef);
12.14 }
12.15
12.16 -- (SecExternalItemType) keyType {
12.17 +- (SecExternalItemType) keyClass {
12.18 AssertAbstractMethod();
12.19 }
12.20
12.21 +#if MYCRYPTO_USE_IPHONE_API
12.22 +- (SecExternalItemType) keyType {
12.23 + return NULL;
12.24 +}
12.25 +#endif
12.26
12.27 - (SecKeyRef) keyRef {
12.28 return (SecKeyRef) self.keychainItemRef;
13.1 --- a/MYKeychain-iPhone.m Sat Jun 06 15:36:35 2009 -0700
13.2 +++ b/MYKeychain-iPhone.m Sun Jun 07 21:53:56 2009 -0700
13.3 @@ -19,6 +19,7 @@
13.4 CFArrayRef _results;
13.5 CFTypeRef _itemClass;
13.6 CFIndex _index;
13.7 + MYKeychainItem *_currentObject;
13.8 }
13.9
13.10 - (id) initWithQuery: (NSMutableDictionary*)query;
13.11 @@ -62,78 +63,57 @@
13.12
13.13 - (MYPublicKey*) publicKeyWithDigest: (MYSHA1Digest*)pubKeyDigest {
13.14 return [MYKeyEnumerator firstItemWithQuery:
13.15 - $mdict({(id)kSecClass, (id)kSecClassKey},
13.16 - {(id)kSecAttrPublicKeyHash, pubKeyDigest.asData},
13.17 - {(id)kSecReturnRef, $true})];
13.18 + $mdict({(id)kSecAttrKeyClass, (id)kSecAttrKeyClassPublic},
13.19 + {(id)kSecAttrApplicationLabel, pubKeyDigest.asData})];
13.20 }
13.21
13.22 - (NSEnumerator*) enumeratePublicKeys {
13.23 - NSMutableDictionary *query = $mdict({(id)kSecClass, (id)kSecClassKey},
13.24 - {(id)kSecAttrKeyClass, (id)kSecAttrKeyClassPublic},
13.25 - {(id)kSecMatchLimit, (id)kSecMatchLimitAll},
13.26 - {(id)kSecReturnRef, $true});
13.27 + NSMutableDictionary *query = $mdict({(id)kSecAttrKeyClass, (id)kSecAttrKeyClassPublic});
13.28 return [[[MYKeyEnumerator alloc] initWithQuery: query] autorelease];
13.29 }
13.30
13.31
13.32 - (MYPrivateKey*) privateKeyWithDigest: (MYSHA1Digest*)pubKeyDigest {
13.33 return [MYKeyEnumerator firstItemWithQuery:
13.34 - $mdict({(id)kSecClass, (id)kSecClassKey},
13.35 - {(id)kSecAttrKeyClass, (id)kSecAttrKeyClassPrivate},
13.36 - {(id)kSecAttrPublicKeyHash, pubKeyDigest.asData},
13.37 - {(id)kSecReturnRef, $true})];
13.38 + $mdict({(id)kSecAttrKeyClass, (id)kSecAttrKeyClassPrivate},
13.39 + {(id)kSecAttrApplicationLabel, pubKeyDigest.asData})];
13.40 }
13.41
13.42 - (NSEnumerator*) enumeratePrivateKeys {
13.43 - NSMutableDictionary *query = $mdict({(id)kSecClass, (id)kSecClassKey},
13.44 - {(id)kSecAttrKeyClass, (id)kSecAttrKeyClassPrivate},
13.45 - {(id)kSecMatchLimit, (id)kSecMatchLimitAll},
13.46 - {(id)kSecReturnRef, $true});
13.47 + NSMutableDictionary *query = $mdict({(id)kSecAttrKeyClass, (id)kSecAttrKeyClassPrivate});
13.48 return [[[MYKeyEnumerator alloc] initWithQuery: query] autorelease];
13.49 }
13.50
13.51 - (MYCertificate*) certificateWithDigest: (MYSHA1Digest*)pubKeyDigest {
13.52 return [MYKeyEnumerator firstItemWithQuery:
13.53 $mdict({(id)kSecClass, (id)kSecClassCertificate},
13.54 - {(id)kSecAttrPublicKeyHash, pubKeyDigest.asData},
13.55 - {(id)kSecReturnRef, $true})];
13.56 + {(id)kSecAttrPublicKeyHash, pubKeyDigest.asData})];
13.57 }
13.58
13.59 - (NSEnumerator*) enumerateCertificates {
13.60 - NSMutableDictionary *query = $mdict({(id)kSecClass, (id)kSecClassCertificate},
13.61 - {(id)kSecMatchLimit, (id)kSecMatchLimitAll},
13.62 - {(id)kSecReturnRef, $true});
13.63 + NSMutableDictionary *query = $mdict({(id)kSecClass, (id)kSecClassCertificate});
13.64 return [[[MYKeyEnumerator alloc] initWithQuery: query] autorelease];
13.65 }
13.66
13.67 - (MYIdentity*) identityWithDigest: (MYSHA1Digest*)pubKeyDigest {
13.68 return [MYKeyEnumerator firstItemWithQuery:
13.69 $mdict({(id)kSecClass, (id)kSecClassIdentity},
13.70 - {(id)kSecAttrPublicKeyHash, pubKeyDigest.asData},
13.71 - {(id)kSecReturnRef, $true})];
13.72 + {(id)kSecAttrPublicKeyHash, pubKeyDigest.asData})];
13.73 }
13.74
13.75 - (NSEnumerator*) enumerateIdentities {
13.76 - NSMutableDictionary *query = $mdict({(id)kSecClass, (id)kSecClassIdentity},
13.77 - {(id)kSecMatchLimit, (id)kSecMatchLimitAll},
13.78 - {(id)kSecReturnRef, $true});
13.79 + NSMutableDictionary *query = $mdict({(id)kSecClass, (id)kSecClassIdentity});
13.80 return [[[MYKeyEnumerator alloc] initWithQuery: query] autorelease];
13.81 }
13.82
13.83 - (NSEnumerator*) enumerateSymmetricKeys {
13.84 - NSMutableDictionary *query = $mdict({(id)kSecClass, (id)kSecClassKey},
13.85 - {(id)kSecAttrKeyClass, (id)kSecAttrKeyClassSymmetric},
13.86 - {(id)kSecMatchLimit, (id)kSecMatchLimitAll},
13.87 - {(id)kSecReturnRef, $true});
13.88 + NSMutableDictionary *query = $mdict({(id)kSecAttrKeyClass, (id)kSecAttrKeyClassSymmetric});
13.89 return [[[MYKeyEnumerator alloc] initWithQuery: query] autorelease];
13.90 }
13.91
13.92 - (NSEnumerator*) symmetricKeysWithAlias: (NSString*)alias {
13.93 - NSMutableDictionary *query = $mdict({(id)kSecClass, (id)kSecClassKey},
13.94 - {(id)kSecAttrKeyClass, (id)kSecAttrKeyClassSymmetric},
13.95 - {(id)kSecAttrApplicationTag, alias},
13.96 - {(id)kSecMatchLimit, (id)kSecMatchLimitAll},
13.97 - {(id)kSecReturnRef, $true});
13.98 + NSMutableDictionary *query = $mdict({(id)kSecAttrKeyClass, (id)kSecAttrKeyClassSymmetric},
13.99 + {(id)kSecAttrApplicationTag, alias});
13.100 return [[[MYKeyEnumerator alloc] initWithQuery: query] autorelease];
13.101 }
13.102
13.103 @@ -187,33 +167,54 @@
13.104 - (id) initWithQuery: (NSMutableDictionary*)query {
13.105 self = [super init];
13.106 if (self) {
13.107 - if (![query objectForKey: (id)kSecMatchLimit])
13.108 - [query setObject: (id)kSecMatchLimitAll forKey: (id)kSecMatchLimit];
13.109 + _itemClass = (CFTypeRef)[query objectForKey: (id)kSecAttrKeyClass];
13.110 + if (_itemClass)
13.111 + [query setObject: (id)kSecClassKey forKey: (id)kSecClass];
13.112 + else
13.113 + _itemClass = (CFTypeRef)[query objectForKey: (id)kSecClass];
13.114 + Assert(_itemClass);
13.115 + CFRetain(_itemClass);
13.116 +
13.117 + // Ask for all results unless caller specified fewer:
13.118 + CFTypeRef limit = [query objectForKey: (id)kSecMatchLimit];
13.119 + if (! limit) {
13.120 + limit = kSecMatchLimitAll;
13.121 + [query setObject: (id)limit forKey: (id)kSecMatchLimit];
13.122 + }
13.123 +
13.124 + [query setObject: $true forKey: (id)kSecReturnRef];
13.125 +
13.126 OSStatus err = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef*)&_results);
13.127 if (err && err != errSecItemNotFound) {
13.128 check(err,@"SecItemCopyMatching");
13.129 [self release];
13.130 return nil;
13.131 }
13.132 - if (_results) CFRetain(_results);
13.133 - _itemClass = (CFTypeRef)[query objectForKey: (id)kSecClass];
13.134 - if (_itemClass == kSecClassKey)
13.135 - _itemClass = (CFTypeRef)[query objectForKey: (id)kSecAttrKeyClass];
13.136 - if (_itemClass) CFRetain(_itemClass);
13.137 + Log(@"Enumerator results = %@", _results);//TEMP
13.138 +
13.139 + if (_results && CFEqual(limit,kSecMatchLimitOne)) {
13.140 + // If you ask for only one, it gives you the object back instead of an array:
13.141 + CFArrayRef resultsArray = CFArrayCreate(NULL, (const void**)&_results, 1,
13.142 + &kCFTypeArrayCallBacks);
13.143 + CFRelease(_results);
13.144 + _results = resultsArray;
13.145 + }
13.146 }
13.147 return self;
13.148 }
13.149
13.150 + (id) firstItemWithQuery: (NSMutableDictionary*)query {
13.151 + [query setObject: (id)kSecMatchLimitOne forKey: (id)kSecMatchLimit];
13.152 MYKeyEnumerator *e = [[self alloc] initWithQuery: query];
13.153 - MYKeychainItem *item = e.nextObject;
13.154 + MYKeychainItem *item = [e.nextObject retain];
13.155 [e release];
13.156 - return item;
13.157 + return [item autorelease];
13.158 }
13.159
13.160 - (void) dealloc
13.161 {
13.162 - if (_itemClass) CFRelease(_itemClass);
13.163 + [_currentObject release];
13.164 + CFRelease(_itemClass);
13.165 if (_results) CFRelease(_results);
13.166 [super dealloc];
13.167 }
13.168 @@ -222,23 +223,24 @@
13.169 - (id) nextObject {
13.170 if (!_results)
13.171 return nil;
13.172 - MYKeychainItem *next = nil;
13.173 - while (next==nil && _index < CFArrayGetCount(_results)) {
13.174 + setObj(&_currentObject,nil);
13.175 + while (_currentObject==nil && _index < CFArrayGetCount(_results)) {
13.176 CFTypeRef found = CFArrayGetValueAtIndex(_results, _index++);
13.177 if (_itemClass == kSecAttrKeyClassPrivate) {
13.178 - next = [[MYPrivateKey alloc] initWithKeyRef: (SecKeyRef)found];
13.179 + _currentObject = [[MYPrivateKey alloc] initWithKeyRef: (SecKeyRef)found];
13.180 } else if (_itemClass == kSecAttrKeyClassPublic) {
13.181 - next = [[[MYPublicKey alloc] initWithKeyRef: (SecKeyRef)found] autorelease];
13.182 + _currentObject = [[MYPublicKey alloc] initWithKeyRef: (SecKeyRef)found];
13.183 } else if (_itemClass == kSecAttrKeyClassSymmetric) {
13.184 - next = [[[MYSymmetricKey alloc] initWithKeyRef: (SecKeyRef)found] autorelease];
13.185 + _currentObject = [[MYSymmetricKey alloc] initWithKeyRef: (SecKeyRef)found];
13.186 } else if (_itemClass == kSecClassCertificate) {
13.187 - next = [[[MYCertificate alloc] initWithCertificateRef: (SecCertificateRef)found] autorelease];
13.188 + _currentObject = [[MYCertificate alloc] initWithCertificateRef: (SecCertificateRef)found];
13.189 } else if (_itemClass == kSecClassIdentity) {
13.190 - next = [[[MYIdentity alloc] initWithIdentityRef: (SecIdentityRef)found] autorelease];
13.191 + _currentObject = [[MYIdentity alloc] initWithIdentityRef: (SecIdentityRef)found];
13.192 + } else {
13.193 + Assert(NO,@"Unknown _itemClass: %@",_itemClass);
13.194 }
13.195 - CFRelease(found);
13.196 }
13.197 - return next;
13.198 + return _currentObject;
13.199 }
13.200
13.201
14.1 --- a/MYKeychainItem.m Sat Jun 06 15:36:35 2009 -0700
14.2 +++ b/MYKeychainItem.m Sun Jun 07 21:53:56 2009 -0700
14.3 @@ -17,13 +17,14 @@
14.4 @implementation MYKeychainItem
14.5
14.6
14.7 -- (id) initWithKeychainItemRef: (MYKeychainItemRef)itemRef;
14.8 +- (id) initWithKeychainItemRef: (MYKeychainItemRef)itemRef
14.9 {
14.10 Assert(itemRef!=NULL);
14.11 self = [super init];
14.12 if (self != nil) {
14.13 _itemRef = itemRef;
14.14 CFRetain(_itemRef);
14.15 + LogTo(INIT,@"%@, _itemRef=%@", [self class], itemRef);
14.16 }
14.17 return self;
14.18 }
14.19 @@ -213,6 +214,8 @@
14.20 return checkcssm(err,what);
14.21 #endif
14.22 Warn(@"MYCrypto error, %@: %@", what, MYErrorName(NSOSStatusErrorDomain,err));
14.23 + if (err==-50)
14.24 + [NSException raise: NSGenericException format: @"%@ failed with paramErr (-50)",what];
14.25 return NO;
14.26 } else
14.27 return YES;
15.1 --- a/MYPrivateKey.m Sat Jun 06 15:36:35 2009 -0700
15.2 +++ b/MYPrivateKey.m Sun Jun 07 21:53:56 2009 -0700
15.3 @@ -175,11 +175,18 @@
15.4
15.5 @synthesize publicKey=_publicKey;
15.6
15.7 -- (MYSHA1Digest*) publicKeyDigest {
15.8 - return _publicKey.publicKeyDigest;
15.9 +- (MYSHA1Digest*) _keyDigest {
15.10 + if (_publicKey)
15.11 + return _publicKey.publicKeyDigest;
15.12 + else
15.13 + return [MYSHA1Digest digestFromDigestData: [self _attribute: kSecAttrApplicationLabel]];
15.14 }
15.15
15.16 -- (SecExternalItemType) keyType {
15.17 +- (MYSHA1Digest*) publicKeyDigest {
15.18 + return self._keyDigest;
15.19 +}
15.20 +
15.21 +- (SecExternalItemType) keyClass {
15.22 #if MYCRYPTO_USE_IPHONE_API
15.23 return kSecAttrKeyClassPublic;
15.24 #else
15.25 @@ -187,6 +194,12 @@
15.26 #endif
15.27 }
15.28
15.29 +#if MYCRYPTO_USE_IPHONE_API
15.30 +- (SecExternalItemType) keyType {
15.31 + return kSecAttrKeyTypeRSA;
15.32 +}
15.33 +#endif
15.34 +
15.35 - (NSData *) keyData {
15.36 [NSException raise: NSGenericException format: @"Can't access keyData of a PrivateKey"];
15.37 return nil;
16.1 --- a/MYPublicKey.m Sat Jun 06 15:36:35 2009 -0700
16.2 +++ b/MYPublicKey.m Sun Jun 07 21:53:56 2009 -0700
16.3 @@ -36,7 +36,7 @@
16.4 [super dealloc];
16.5 }
16.6
16.7 -- (SecExternalItemType) keyType {
16.8 +- (SecExternalItemType) keyClass {
16.9 #if MYCRYPTO_USE_IPHONE_API
16.10 return kSecAttrKeyClassPublic;
16.11 #else
16.12 @@ -44,6 +44,16 @@
16.13 #endif
16.14 }
16.15
16.16 +#if MYCRYPTO_USE_IPHONE_API
16.17 +- (SecExternalItemType) keyType {
16.18 + return kSecAttrKeyTypeRSA;
16.19 +}
16.20 +
16.21 +- (MYSHA1Digest*) _keyDigest {
16.22 + return (MYSHA1Digest*) [MYSHA1Digest digestFromDigestData: [self _attribute: kSecAttrApplicationLabel]];
16.23 +}
16.24 +#endif
16.25 +
16.26 - (NSUInteger)hash {
16.27 return self.publicKeyDigest.hash;
16.28 }
17.1 --- a/MYSymmetricKey-iPhone.m Sat Jun 06 15:36:35 2009 -0700
17.2 +++ b/MYSymmetricKey-iPhone.m Sun Jun 07 21:53:56 2009 -0700
17.3 @@ -43,27 +43,27 @@
17.4 Assert(algorithm <= kCCAlgorithmRC4);
17.5 Assert(keyData);
17.6 NSNumber *keySizeInBits = [NSNumber numberWithUnsignedInt: keyData.length * 8];
17.7 - NSDictionary *keyAttrs = $dict( {(id)kSecClass, (id)kSecClassKey},
17.8 - //{(id)kSecAttrKeyClass, (id)kSecAttrKeyClassSymmetric},
17.9 - {(id)kSecAttrKeyType, [NSNumber numberWithUnsignedInt: kCSSMAlgorithms[algorithm]]},
17.10 - {(id)kSecAttrKeySizeInBits, keySizeInBits},
17.11 - {(id)kSecAttrEffectiveKeySize, keySizeInBits},
17.12 - {(id)kSecAttrIsPermanent, keychain ?$true :$false},
17.13 - {(id)kSecAttrCanEncrypt, $true},
17.14 - {(id)kSecAttrCanDecrypt, $true},
17.15 - {(id)kSecAttrCanWrap, $false},
17.16 - {(id)kSecAttrCanUnwrap, $false},
17.17 - {(id)kSecAttrCanDerive, $false},
17.18 - {(id)kSecAttrCanSign, $false},
17.19 - {(id)kSecAttrCanVerify, $false},
17.20 - {(id)kSecValueData, keyData},
17.21 - {(id)kSecReturnPersistentRef, $true});
17.22 - SecKeyRef keyRef = NULL;
17.23 - if (!check(SecItemAdd((CFDictionaryRef)keyAttrs, (CFTypeRef*)&keyRef), @"SecItemAdd")) {
17.24 + NSNumber *keyType = [NSNumber numberWithUnsignedInt: kCSSMAlgorithms[algorithm]];
17.25 + NSMutableDictionary *keyAttrs = $mdict( {(id)kSecClass, (id)kSecClassKey},
17.26 + {(id)kSecAttrKeyClass, (id)kSecAttrKeyClassSymmetric},
17.27 + {(id)kSecAttrKeyType, keyType},
17.28 + {(id)kSecValueData, keyData},
17.29 + {(id)kSecAttrKeySizeInBits, keySizeInBits},
17.30 + {(id)kSecAttrEffectiveKeySize, keySizeInBits},
17.31 + {(id)kSecAttrIsPermanent, keychain ?$true :$false},
17.32 + {(id)kSecAttrCanEncrypt, $true},
17.33 + {(id)kSecAttrCanDecrypt, $true},
17.34 + {(id)kSecAttrCanWrap, $false},
17.35 + {(id)kSecAttrCanUnwrap, $false},
17.36 + {(id)kSecAttrCanDerive, $false},
17.37 + {(id)kSecAttrCanSign, $false},
17.38 + {(id)kSecAttrCanVerify, $false},
17.39 + {(id)kSecReturnPersistentRef, $true});
17.40 + SecKeyRef keyRef = [[self class] _addKeyWithInfo: keyAttrs];
17.41 + if (!keyRef) {
17.42 [self release];
17.43 return nil;
17.44 }
17.45 - Assert(keyRef, @"SecItemAdd didn't return anything");
17.46 self = [self initWithKeyRef: keyRef];
17.47 CFRelease(keyRef);
17.48 return self;
17.49 @@ -93,7 +93,7 @@
17.50 }
17.51
17.52
17.53 -- (SecExternalItemType) keyType {
17.54 +- (SecExternalItemType) keyClass {
17.55 return kSecAttrKeyClassSymmetric;
17.56 }
17.57
18.1 --- a/MYSymmetricKey.m Sat Jun 06 15:36:35 2009 -0700
18.2 +++ b/MYSymmetricKey.m Sun Jun 07 21:53:56 2009 -0700
18.3 @@ -283,7 +283,7 @@
18.4 #endif
18.5
18.6
18.7 -- (SecExternalItemType) keyType {
18.8 +- (SecExternalItemType) keyClass {
18.9 return kSecItemTypeSessionKey;
18.10 }
18.11