Fixed iPhone OS build. (issue 3)
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 - (unsigned) keySizeInBits {
110 return [[self _attribute: kSecAttrKeySizeInBits] intValue];
113 - (SecKeyRef) keyRef {
114 return (SecKeyRef) self.keychainItemRef;
118 - (id) _attribute: (CFTypeRef)attribute {
119 NSDictionary *info = $dict({(id)kSecValueRef, (id)self.keyRef},
120 {(id)kSecAttrIsPermanent, (self.isPersistent ?$true :$false)},
121 {(id)kSecReturnAttributes, $true});
122 CFDictionaryRef attrs = NULL;
123 if (!check(SecItemCopyMatching((CFDictionaryRef)info, (CFTypeRef*)&attrs), @"SecItemCopyMatching"))
125 CFTypeRef rawValue = CFDictionaryGetValue(attrs,attribute);
126 id value = rawValue ?[[(id)CFMakeCollectable(rawValue) retain] autorelease] :nil;
131 - (BOOL) setValue: (NSString*)value ofAttribute: (SecKeychainAttrType)attribute {
133 value = (id)[NSNull null];
134 NSDictionary *query = $dict( {(id)kSecValueRef, (id)self.keyRef} );
135 NSDictionary *attrs = $dict( {(id)attribute, value} );
136 return check(SecItemUpdate((CFDictionaryRef)query, (CFDictionaryRef)attrs), @"SecItemUpdate");
141 return [self _attribute: kSecAttrLabel];
144 - (void) setName: (NSString*)name {
145 [self setValue: name ofAttribute: kSecAttrLabel];
148 - (NSString*) alias {
149 return [self _attribute: kSecAttrApplicationTag];
152 - (void) setAlias: (NSString*)alias {
153 [self setValue: alias ofAttribute: kSecAttrApplicationTag];
159 /** Asymmetric encryption/decryption; used by MYPublicKey and MYPrivateKey. */
160 - (NSData*) _crypt: (NSData*)data operation: (BOOL)operation {
162 size_t dataLength = data.length;
163 SecKeyRef key = self.keyRef;
164 size_t outputLength = MAX(dataLength, SecKeyGetBlockSize(key));
165 void *outputBuf = malloc(outputLength);
166 if (!outputBuf) return nil;
169 err = SecKeyEncrypt(key, kSecPaddingNone,//PKCS1,
170 data.bytes, dataLength,
171 outputBuf, &outputLength);
173 err = SecKeyDecrypt(key, kSecPaddingNone,//PKCS1,
174 data.bytes, dataLength,
175 outputBuf, &outputLength);
178 Warn(@"%scrypting failed (%i)", (operation ?"En" :"De"), err);
179 // Note: One of the errors I've seen is -9809, which is errSSLCrypto (SecureTransport.h)
182 return [NSData dataWithBytesNoCopy: outputBuf length: outputLength freeWhenDone: YES];
189 #endif MYCRYPTO_USE_IPHONE_API
194 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
196 Redistribution and use in source and binary forms, with or without modification, are permitted
197 provided that the following conditions are met:
199 * Redistributions of source code must retain the above copyright notice, this list of conditions
200 and the following disclaimer.
201 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
202 and the following disclaimer in the documentation and/or other materials provided with the
205 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
206 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
207 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
208 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
209 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
210 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
211 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
212 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.