Factored out the name accessors of MYParsedCertificate into a new class MYCertificateName, so that both subject and issuer can be accessed. A bit of other cleanup too.
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 - (NSString*) description {
44 return $sprintf(@"%@[%@ /%p]", [self class], (self.name ?:@""), self.keychainItemRef);
47 - (SecExternalItemType) keyType {
48 AssertAbstractMethod();
52 - (SecKeyRef) keyRef {
53 return (SecKeyRef) self.keychainItemRef;
56 - (const CSSM_KEY*) cssmKey {
57 const CSSM_KEY *cssmKey = NULL;
58 Assert(check(SecKeyGetCSSMKey(self.keyRef, &cssmKey), @"SecKeyGetCSSMKey"),
59 @"Failed to get CSSM_KEY");
63 - (const CSSM_CSP_HANDLE) cssmCSPHandle {
64 CSSM_CSP_HANDLE cspHandle = 0;
65 Assert(check(SecKeyGetCSPHandle(self.keyRef, &cspHandle), @"SecKeyGetCSPHandle"),
66 @"Failed to get CSSM_CSP_HANDLE");
70 - (CSSM_ALGORITHMS) cssmAlgorithm {
71 return self.cssmKey->KeyHeader.AlgorithmId;
74 - (const CSSM_ACCESS_CREDENTIALS*) cssmCredentialsForOperation: (CSSM_ACL_AUTHORIZATION_TAG)operation
75 type: (SecCredentialType)type
76 error: (NSError**)outError
78 const CSSM_ACCESS_CREDENTIALS *credentials = NULL;
79 OSStatus err = SecKeyGetCredentials(self.keyRef,
83 if (!MYReturnError(outError, err,NSOSStatusErrorDomain, @"Couldn't get credentials for key"))
88 - (SecExternalFormat) _externalFormat {
89 return kSecFormatRawKey;
93 CFDataRef data = NULL;
94 if (check(SecKeychainItemExport(self.keyRef, self._externalFormat, 0, NULL, &data),
95 @"SecKeychainItemExport"))
96 return [(id)CFMakeCollectable(data) autorelease];
102 return [self stringValueOfAttribute: kSecKeyPrintName];
105 - (void) setName: (NSString*)name {
106 [self setValue: name ofAttribute: kSecKeyPrintName];
109 - (NSString*) comment {
110 return [self stringValueOfAttribute: kSecKeyApplicationTag];
113 - (void) setComment: (NSString*)comment {
114 [self setValue: comment ofAttribute: kSecKeyApplicationTag];
117 - (NSString*) alias {
118 return [self stringValueOfAttribute: kSecKeyAlias];
121 - (void) setAlias: (NSString*)alias {
122 [self setValue: alias ofAttribute: kSecKeyAlias];
127 #pragma mark UTILITY FUNCTIONS:
130 SecKeyRef importKey(NSData *data,
131 SecExternalItemType type,
132 SecKeychainRef keychain,
133 SecKeyImportExportParameters *params) {
134 SecExternalFormat inputFormat = (type==kSecItemTypeSessionKey) ?kSecFormatRawKey :kSecFormatUnknown;
135 CFArrayRef items = NULL;
137 params->version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
138 params->flags |= kSecKeyImportOnlyOne;
139 params->keyAttributes |= CSSM_KEYATTR_EXTRACTABLE;
141 params->keyAttributes |= CSSM_KEYATTR_PERMANENT;
142 if (type==kSecItemTypeSessionKey)
143 params->keyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT;
144 else if (type==kSecItemTypePublicKey)
145 params->keyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP;
146 else if (type==kSecItemTypePrivateKey)
147 params->keyUsage = CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN;
149 if (!check(SecKeychainItemImport((CFDataRef)data, NULL, &inputFormat, &type,
150 0, params, keychain, &items),
151 @"SecKeychainItemImport"))
153 if (!items || CFArrayGetCount(items) != 1)
155 SecKeyRef key = (SecKeyRef)CFRetain(CFArrayGetValueAtIndex(items,0));
157 return key; // caller must CFRelease
161 - (MYSHA1Digest*) _keyDigest {
162 MYSHA1Digest *digest = nil;
163 CSSM_DATA *keyDigest = NULL;
164 CSSM_CC_HANDLE context = [self _createPassThroughContext];
166 if (checkcssm(CSSM_CSP_PassThrough(context, CSSM_APPLECSP_KEYDIGEST, NULL, (void**)&keyDigest),
167 @"CSSM_CSP_PassThrough")) {
168 if (keyDigest && keyDigest->Data) {
169 digest = [[[MYSHA1Digest alloc] initWithRawDigest: keyDigest->Data
170 length: keyDigest->Length] autorelease];
173 SecKeyRef keyRef = self.keyRef;
174 // Note - CSSM_CSP_PassThrough fails on a couple of private keys I've seen; it seems to
175 // be ones that are either expired or don't have a matching public key at all (?)
176 Warn(@"Failed to get digest of SecKeyRef %p (name='%@' appTag='%@')",
180 NSData *digestData = [[self class] _getAttribute: kSecKeyLabel
181 ofItem: (SecKeychainItemRef)keyRef];
183 digest = (MYSHA1Digest*) [MYSHA1Digest digestFromDigestData: digestData];
185 Warn(@"Digest property of key %p was invalid SHA-1: %@", keyRef,digestData);
188 CSSM_DeleteContext(context);
194 /** Asymmetric encryption/decryption; used by MYPublicKey and MYPrivateKey. */
195 - (NSData*) _crypt: (NSData*)data operation: (BOOL)operation {
197 const CSSM_ACCESS_CREDENTIALS *credentials;
198 credentials = [self cssmCredentialsForOperation: (operation ?CSSM_ACL_AUTHORIZATION_ENCRYPT
199 :CSSM_ACL_AUTHORIZATION_DECRYPT)
200 type: kSecCredentialTypeDefault
205 CSSM_CC_HANDLE ccHandle;
206 if (!checkcssm(CSSM_CSP_CreateAsymmetricContext(self.cssmCSPHandle,
212 @"CSSM_CSP_CreateAsymmetricContext"))
215 CSSM_DATA original = {data.length, (void*)data.bytes};
216 CSSM_DATA result = {};
220 ok = checkcssm(CSSM_EncryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result),
221 @"CSSM_EncryptData");
223 ok = checkcssm(CSSM_DecryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result),
224 @"CSSM_DecryptData");
225 CSSM_DeleteContext(ccHandle);
226 return ok ?[NSData dataWithBytesNoCopy: result.Data length: outputLength freeWhenDone: YES] :nil;
230 - (CSSM_CC_HANDLE) _createSignatureContext: (CSSM_ALGORITHMS)algorithm {
231 const CSSM_ACCESS_CREDENTIALS *credentials;
232 credentials = [self cssmCredentialsForOperation: CSSM_ACL_AUTHORIZATION_SIGN
233 type: kSecCredentialTypeDefault
236 CSSM_CC_HANDLE ccHandle = 0;
237 if (checkcssm(CSSM_CSP_CreateSignatureContext(self.cssmCSPHandle,
242 @"CSSM_CSP_CreateSignatureContext") )
248 - (CSSM_CC_HANDLE) _createPassThroughContext
250 CSSM_CC_HANDLE ccHandle = 0;
251 if (checkcssm(CSSM_CSP_CreatePassThroughContext(self.cssmCSPHandle, self.cssmKey, &ccHandle),
252 @"CSSM_CSP_CreatePassThroughContext") )
261 #endif MYCRYPTO_USE_IPHONE_API
266 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
268 Redistribution and use in source and binary forms, with or without modification, are permitted
269 provided that the following conditions are met:
271 * Redistributions of source code must retain the above copyright notice, this list of conditions
272 and the following disclaimer.
273 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
274 and the following disclaimer in the documentation and/or other materials provided with the
277 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
278 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
279 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
280 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
281 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
282 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
283 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
284 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.