MYCertificate now checks validity of self-signed certs loaded from the keychain (because the Security framework doesn't validate self-signed certs.)
5 // Created by Jens Alfke on 4/4/09.
6 // Copyright 2009 Jens Alfke. All rights reserved.
10 #import "MYCrypto_Private.h"
12 #if MYCRYPTO_USE_IPHONE_API
15 #import "MYErrorUtils.h"
22 - (id) initWithKeyRef: (SecKeyRef)key {
23 return [self initWithKeychainItemRef: (SecKeychainItemRef)key];
27 - (id) _initWithKeyData: (NSData*)data
28 forKeychain: (SecKeychainRef)keychain
30 NSMutableDictionary *info = $mdict({(id)kSecClass, (id)kSecClassKey},
31 {(id)kSecAttrKeyType, (id)self.keyType},
32 {(id)kSecValueData, data},
33 {(id)kSecAttrIsPermanent, (keychain ?$true :$false)},
34 {(id)kSecReturnPersistentRef, (keychain ?$true :$false)} );
35 SecKeyRef key = (SecKeyRef)[MYKeychain _addItemWithInfo: info];
40 self = [self initWithKeyRef: (SecKeyRef)key];
43 _keyData = [data copy];
46 AssertEqual(self.keyData, data);
51 - (id) initWithKeyData: (NSData*)data {
52 return [self _initWithKeyData: data forKeychain: nil];
62 /*- (NSData*) persistentRef {
63 NSDictionary *info = $dict( {(id)kSecValueRef, (id)self.keyRef},
64 //{(id)kSecAttrIsPermanent, (self.isPersistent ?$true :$false)},
65 {(id)kSecReturnPersistentRef, $true} );
67 if (!check(SecItemCopyMatching((CFDictionaryRef)info, (CFTypeRef*)&data), @"SecItemCopyMatching"))
70 Warn(@"MYKey persistentRef couldn't get ref");
71 return [NSMakeCollectable(data) autorelease];
75 - (SecExternalItemType) keyClass {
76 AssertAbstractMethod();
79 - (SecExternalItemType) keyType {
87 NSDictionary *info = $dict( {(id)kSecValueRef, (id)self.keyRef},
88 //{(id)kSecAttrIsPermanent, (self.isPersistent ?$true :$false)},
89 {(id)kSecReturnData, $true} );
91 if (!check(SecItemCopyMatching((CFDictionaryRef)info, (CFTypeRef*)&data), @"SecItemCopyMatching")) {
92 Log(@"SecItemCopyMatching failed; input = %@", info);
96 _keyData = NSMakeCollectable(data);
99 // The format of this data is not documented. There's been some reverse-engineering:
100 // https://devforums.apple.com/message/32089#32089
101 // Apparently it is a DER-formatted sequence of a modulus followed by an exponent.
102 // This can be converted to OpenSSL format by wrapping it in some additional DER goop.
105 - (MYSHA1Digest*) _keyDigest {
106 return [self.keyData my_SHA1Digest];
109 - (SecKeyRef) keyRef {
110 return (SecKeyRef) self.keychainItemRef;
114 - (id) _attribute: (CFTypeRef)attribute {
115 NSDictionary *info = $dict({(id)kSecValueRef, (id)self.keyRef},
116 {(id)kSecAttrIsPermanent, (self.isPersistent ?$true :$false)},
117 {(id)kSecReturnAttributes, $true});
118 CFDictionaryRef attrs = NULL;
119 if (!check(SecItemCopyMatching((CFDictionaryRef)info, (CFTypeRef*)&attrs), @"SecItemCopyMatching"))
121 CFTypeRef rawValue = CFDictionaryGetValue(attrs,attribute);
122 id value = rawValue ?[[(id)CFMakeCollectable(rawValue) retain] autorelease] :nil;
127 - (BOOL) setValue: (NSString*)value ofAttribute: (SecKeychainAttrType)attribute {
129 value = (id)[NSNull null];
130 NSDictionary *query = $dict( {(id)kSecValueRef, (id)self.keyRef} );
131 NSDictionary *attrs = $dict( {(id)attribute, value} );
132 return check(SecItemUpdate((CFDictionaryRef)query, (CFDictionaryRef)attrs), @"SecItemUpdate");
137 return [self _attribute: kSecAttrLabel];
140 - (void) setName: (NSString*)name {
141 [self setValue: name ofAttribute: kSecAttrLabel];
144 - (NSString*) alias {
145 return [self _attribute: kSecAttrApplicationTag];
148 - (void) setAlias: (NSString*)alias {
149 [self setValue: alias ofAttribute: kSecAttrApplicationTag];
155 /** Asymmetric encryption/decryption; used by MYPublicKey and MYPrivateKey. */
156 - (NSData*) _crypt: (NSData*)data operation: (BOOL)operation {
158 size_t dataLength = data.length;
159 SecKeyRef key = self.keyRef;
160 size_t outputLength = MAX(dataLength, SecKeyGetBlockSize(key));
161 void *outputBuf = malloc(outputLength);
162 if (!outputBuf) return nil;
165 err = SecKeyEncrypt(key, kSecPaddingNone,//PKCS1,
166 data.bytes, dataLength,
167 outputBuf, &outputLength);
169 err = SecKeyDecrypt(key, kSecPaddingNone,//PKCS1,
170 data.bytes, dataLength,
171 outputBuf, &outputLength);
174 Warn(@"%scrypting failed (%i)", (operation ?"En" :"De"), err);
175 // Note: One of the errors I've seen is -9809, which is errSSLCrypto (SecureTransport.h)
178 return [NSData dataWithBytesNoCopy: outputBuf length: outputLength freeWhenDone: YES];
185 #endif MYCRYPTO_USE_IPHONE_API
190 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
192 Redistribution and use in source and binary forms, with or without modification, are permitted
193 provided that the following conditions are met:
195 * Redistributions of source code must retain the above copyright notice, this list of conditions
196 and the following disclaimer.
197 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
198 and the following disclaimer in the documentation and/or other materials provided with the
201 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
202 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
203 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
204 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
205 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
206 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
207 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
208 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.