Updated the README for the 0.1 release.
5 // Created by Jens Alfke on 3/21/09.
6 // Copyright 2009 Jens Alfke. All rights reserved.
10 #import "MYCrypto_Private.h"
12 #import "MYErrorUtils.h"
14 #if !MYCRYPTO_USE_IPHONE_API
21 - (id) initWithKeyRef: (SecKeyRef)key {
22 return [super initWithKeychainItemRef: (SecKeychainItemRef)key];
25 - (id) _initWithKeyData: (NSData*)data
26 forKeychain: (SecKeychainRef)keychain {
27 SecKeyImportExportParameters params = {};
28 SecKeyRef key = importKey(data, self.keyType, keychain, ¶ms);
33 self = [self initWithKeyRef: key];
38 - (id) initWithKeyData: (NSData*)data {
39 return [self _initWithKeyData: data forKeychain: nil];
43 - (SecExternalItemType) keyType {
44 AssertAbstractMethod();
48 - (SecKeyRef) keyRef {
49 return (SecKeyRef) self.keychainItemRef;
52 - (const CSSM_KEY*) cssmKey {
53 const CSSM_KEY *cssmKey = NULL;
54 Assert(check(SecKeyGetCSSMKey(self.keyRef, &cssmKey), @"SecKeyGetCSSMKey"),
55 @"Failed to get CSSM_KEY");
59 - (const CSSM_CSP_HANDLE) cssmCSPHandle {
60 CSSM_CSP_HANDLE cspHandle = 0;
61 Assert(check(SecKeyGetCSPHandle(self.keyRef, &cspHandle), @"SecKeyGetCSPHandle"),
62 @"Failed to get CSSM_CSP_HANDLE");
66 - (const CSSM_ACCESS_CREDENTIALS*) cssmCredentialsForOperation: (CSSM_ACL_AUTHORIZATION_TAG)operation
67 type: (SecCredentialType)type
68 error: (NSError**)outError
70 const CSSM_ACCESS_CREDENTIALS *credentials = NULL;
71 OSStatus err = SecKeyGetCredentials(self.keyRef,
75 if (!MYReturnError(outError, err,NSOSStatusErrorDomain, @"Couldn't get credentials for key"))
80 - (NSData*) exportKeyInFormat: (SecExternalFormat)format withPEM: (BOOL)withPEM {
81 CFDataRef data = NULL;
82 if (check(SecKeychainItemExport(self.keyRef, format, (withPEM ?kSecItemPemArmour :0), NULL, &data),
83 @"SecKeychainItemExport"))
84 return [(id)CFMakeCollectable(data) autorelease];
90 return [self exportKeyInFormat: kSecFormatRawKey withPEM: NO];
94 return [self stringValueOfAttribute: kSecKeyPrintName];
97 - (void) setName: (NSString*)name {
98 [self setValue: name ofAttribute: kSecKeyPrintName];
101 - (NSString*) comment {
102 return [self stringValueOfAttribute: kSecKeyApplicationTag];
105 - (void) setComment: (NSString*)comment {
106 [self setValue: comment ofAttribute: kSecKeyApplicationTag];
109 - (NSString*) alias {
110 return [self stringValueOfAttribute: kSecKeyAlias];
113 - (void) setAlias: (NSString*)alias {
114 [self setValue: alias ofAttribute: kSecKeyAlias];
119 #pragma mark UTILITY FUNCTIONS:
122 SecKeyRef importKey(NSData *data,
123 SecExternalItemType type,
124 SecKeychainRef keychain,
125 SecKeyImportExportParameters *params) {
126 SecExternalFormat inputFormat = (type==kSecItemTypeSessionKey) ?kSecFormatRawKey :kSecFormatOpenSSL;
127 CFArrayRef items = NULL;
129 params->version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
130 params->flags |= kSecKeyImportOnlyOne;
131 params->keyAttributes |= CSSM_KEYATTR_EXTRACTABLE;
133 params->keyAttributes |= CSSM_KEYATTR_PERMANENT;
134 if (type==kSecItemTypeSessionKey)
135 params->keyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT;
136 else if (type==kSecItemTypePublicKey)
137 params->keyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY;
138 else if (type==kSecItemTypePrivateKey)
139 params->keyUsage = CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN;
141 if (!check(SecKeychainItemImport((CFDataRef)data, NULL, &inputFormat, &type,
142 0, params, keychain, &items),
143 @"SecKeychainItemImport"))
145 if (!items || CFArrayGetCount(items) != 1)
147 SecKeyRef key = (SecKeyRef)CFRetain(CFArrayGetValueAtIndex(items,0));
149 return key; // caller must CFRelease
153 - (MYSHA1Digest*) _keyDigest {
154 MYSHA1Digest *digest = nil;
155 CSSM_DATA *keyDigest = NULL;
156 CSSM_CC_HANDLE context = [self _createPassThroughContext];
158 if (checkcssm(CSSM_CSP_PassThrough(context, CSSM_APPLECSP_KEYDIGEST, NULL, (void**)&keyDigest),
159 @"CSSM_CSP_PassThrough")) {
160 if (keyDigest && keyDigest->Data) {
161 digest = [[[MYSHA1Digest alloc] initWithRawDigest: keyDigest->Data
162 length: keyDigest->Length] autorelease];
165 SecKeyRef keyRef = self.keyRef;
166 // Note - CSSM_CSP_PassThrough fails on a couple of private keys I've seen; it seems to
167 // be ones that are either expired or don't have a matching public key at all (?)
168 Warn(@"Failed to get digest of SecKeyRef %p (name='%@' appTag='%@')",
172 NSData *digestData = [[self class] _getAttribute: kSecKeyLabel
173 ofItem: (SecKeychainItemRef)keyRef];
175 digest = (MYSHA1Digest*) [MYSHA1Digest digestFromDigestData: digestData];
177 Warn(@"Digest property of key %p was invalid SHA-1: %@", keyRef,digestData);
180 CSSM_DeleteContext(context);
186 /** Asymmetric encryption/decryption; used by MYPublicKey and MYPrivateKey. */
187 - (NSData*) _crypt: (NSData*)data operation: (BOOL)operation {
189 const CSSM_ACCESS_CREDENTIALS *credentials;
190 credentials = [self cssmCredentialsForOperation: (operation ?CSSM_ACL_AUTHORIZATION_ENCRYPT
191 :CSSM_ACL_AUTHORIZATION_DECRYPT)
192 type: kSecCredentialTypeDefault
197 CSSM_CC_HANDLE ccHandle;
198 if (!checkcssm(CSSM_CSP_CreateAsymmetricContext(self.cssmCSPHandle,
204 @"CSSM_CSP_CreateAsymmetricContext"))
207 CSSM_DATA original = {data.length, (void*)data.bytes};
208 CSSM_DATA result = {};
212 ok = checkcssm(CSSM_EncryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result),
213 @"CSSM_EncryptData");
215 ok = checkcssm(CSSM_DecryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result),
216 @"CSSM_DecryptData");
217 CSSM_DeleteContext(ccHandle);
218 return ok ?[NSData dataWithBytesNoCopy: result.Data length: outputLength freeWhenDone: YES] :nil;
222 - (CSSM_CC_HANDLE) _createSignatureContext: (CSSM_ALGORITHMS)algorithm {
223 const CSSM_ACCESS_CREDENTIALS *credentials;
224 credentials = [self cssmCredentialsForOperation: CSSM_ACL_AUTHORIZATION_SIGN
225 type: kSecCredentialTypeDefault
228 CSSM_CC_HANDLE ccHandle = 0;
229 if (checkcssm(CSSM_CSP_CreateSignatureContext(self.cssmCSPHandle,
234 @"CSSM_CSP_CreateSignatureContext") )
240 - (CSSM_CC_HANDLE) _createPassThroughContext
242 CSSM_CC_HANDLE ccHandle = 0;
243 if (checkcssm(CSSM_CSP_CreatePassThroughContext(self.cssmCSPHandle, self.cssmKey, &ccHandle),
244 @"CSSM_CSP_CreatePassThroughContext") )
253 #endif MYCRYPTO_USE_IPHONE_API
258 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
260 Redistribution and use in source and binary forms, with or without modification, are permitted
261 provided that the following conditions are met:
263 * Redistributions of source code must retain the above copyright notice, this list of conditions
264 and the following disclaimer.
265 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
266 and the following disclaimer in the documentation and/or other materials provided with the
269 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
270 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
271 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
272 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
273 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
274 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
275 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
276 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.