* Created class MYCertificateRequest, factored out of MYCertificateInfo.
* Added method to create a MYIdentity directly from a MYCertificateRequest.
* Added raw modulus+exponent accessor and initializer for MYPublicKey.
* Removed obsolete MYCertGen code, and the MYPrivateKey identity-creation method that used it.
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*)keyData
26 forKeychain: (SecKeychainRef)keychain {
28 SecKeyImportExportParameters params = {};
29 SecKeyRef key = importKey(keyData, self.keyType, keychain, ¶ms);
34 self = [self initWithKeyRef: key];
39 - (id) initWithKeyData: (NSData*)data {
40 return [self _initWithKeyData: data forKeychain: nil];
44 - (NSString*) description {
45 return $sprintf(@"%@[%@ /%p]", [self class], (self.name ?:@""), self.keychainItemRef);
48 - (SecExternalItemType) keyType {
49 AssertAbstractMethod();
53 - (SecKeyRef) keyRef {
54 return (SecKeyRef) self.keychainItemRef;
57 - (const CSSM_KEY*) cssmKey {
58 const CSSM_KEY *cssmKey = NULL;
59 Assert(check(SecKeyGetCSSMKey(self.keyRef, &cssmKey), @"SecKeyGetCSSMKey"),
60 @"Failed to get CSSM_KEY");
64 - (const CSSM_CSP_HANDLE) cssmCSPHandle {
65 CSSM_CSP_HANDLE cspHandle = 0;
66 Assert(check(SecKeyGetCSPHandle(self.keyRef, &cspHandle), @"SecKeyGetCSPHandle"),
67 @"Failed to get CSSM_CSP_HANDLE");
71 - (CSSM_ALGORITHMS) cssmAlgorithm {
72 return self.cssmKey->KeyHeader.AlgorithmId;
75 - (const CSSM_ACCESS_CREDENTIALS*) cssmCredentialsForOperation: (CSSM_ACL_AUTHORIZATION_TAG)operation
76 type: (SecCredentialType)type
77 error: (NSError**)outError
79 const CSSM_ACCESS_CREDENTIALS *credentials = NULL;
80 OSStatus err = SecKeyGetCredentials(self.keyRef,
84 if (!MYReturnError(outError, err,NSOSStatusErrorDomain, @"Couldn't get credentials for key"))
89 - (SecExternalFormat) _externalFormat {
90 return kSecFormatRawKey;
94 CFDataRef data = NULL;
95 if (check(SecKeychainItemExport(self.keyRef, self._externalFormat, 0, NULL, &data),
96 @"SecKeychainItemExport"))
97 return [(id)CFMakeCollectable(data) autorelease];
103 return [self stringValueOfAttribute: kSecKeyPrintName];
106 - (void) setName: (NSString*)name {
107 [self setValue: name ofAttribute: kSecKeyPrintName];
110 - (NSString*) comment {
111 return [self stringValueOfAttribute: kSecKeyApplicationTag];
114 - (void) setComment: (NSString*)comment {
115 [self setValue: comment ofAttribute: kSecKeyApplicationTag];
118 - (NSString*) alias {
119 return [self stringValueOfAttribute: kSecKeyAlias];
122 - (void) setAlias: (NSString*)alias {
123 [self setValue: alias ofAttribute: kSecKeyAlias];
128 #pragma mark UTILITY FUNCTIONS:
131 SecKeyRef importKey(NSData *data,
132 SecExternalItemType type,
133 SecKeychainRef keychain,
134 SecKeyImportExportParameters *params) {
135 SecExternalFormat inputFormat = (type==kSecItemTypeSessionKey) ?kSecFormatRawKey :kSecFormatUnknown;
136 CFArrayRef items = NULL;
138 params->version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
139 params->flags |= kSecKeyImportOnlyOne;
140 params->keyAttributes |= CSSM_KEYATTR_EXTRACTABLE;
142 params->keyAttributes |= CSSM_KEYATTR_PERMANENT;
143 if (type==kSecItemTypeSessionKey)
144 params->keyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT;
145 else if (type==kSecItemTypePublicKey)
146 params->keyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP;
147 else if (type==kSecItemTypePrivateKey)
148 params->keyUsage = CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN;
150 if (!check(SecKeychainItemImport((CFDataRef)data, NULL, &inputFormat, &type,
151 0, params, keychain, &items),
152 @"SecKeychainItemImport"))
154 if (!items || CFArrayGetCount(items) != 1)
156 SecKeyRef key = (SecKeyRef)CFRetain(CFArrayGetValueAtIndex(items,0));
158 return key; // caller must CFRelease
162 - (MYSHA1Digest*) _keyDigest {
163 MYSHA1Digest *digest = nil;
164 CSSM_DATA *keyDigest = NULL;
165 CSSM_CC_HANDLE context = [self _createPassThroughContext];
167 if (checkcssm(CSSM_CSP_PassThrough(context, CSSM_APPLECSP_KEYDIGEST, NULL, (void**)&keyDigest),
168 @"CSSM_CSP_PassThrough")) {
169 if (keyDigest && keyDigest->Data) {
170 digest = [[[MYSHA1Digest alloc] initWithRawDigest: keyDigest->Data
171 length: keyDigest->Length] autorelease];
174 SecKeyRef keyRef = self.keyRef;
175 // Note - CSSM_CSP_PassThrough fails on a couple of private keys I've seen; it seems to
176 // be ones that are either expired or don't have a matching public key at all (?)
177 Warn(@"Failed to get digest of SecKeyRef %p (name='%@' appTag='%@')",
181 NSData *digestData = [[self class] _getAttribute: kSecKeyLabel
182 ofItem: (SecKeychainItemRef)keyRef];
184 digest = (MYSHA1Digest*) [MYSHA1Digest digestFromDigestData: digestData];
186 Warn(@"Digest property of key %p was invalid SHA-1: %@", keyRef,digestData);
189 CSSM_DeleteContext(context);
195 /** Asymmetric encryption/decryption; used by MYPublicKey and MYPrivateKey. */
196 - (NSData*) _crypt: (NSData*)data operation: (BOOL)operation {
198 const CSSM_ACCESS_CREDENTIALS *credentials;
199 credentials = [self cssmCredentialsForOperation: (operation ?CSSM_ACL_AUTHORIZATION_ENCRYPT
200 :CSSM_ACL_AUTHORIZATION_DECRYPT)
201 type: kSecCredentialTypeDefault
206 CSSM_CC_HANDLE ccHandle;
207 if (!checkcssm(CSSM_CSP_CreateAsymmetricContext(self.cssmCSPHandle,
213 @"CSSM_CSP_CreateAsymmetricContext"))
216 CSSM_DATA original = {data.length, (void*)data.bytes};
217 CSSM_DATA result = {};
221 ok = checkcssm(CSSM_EncryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result),
222 @"CSSM_EncryptData");
224 ok = checkcssm(CSSM_DecryptData(ccHandle, &original, 1, &result, 1, &outputLength, &result),
225 @"CSSM_DecryptData");
226 CSSM_DeleteContext(ccHandle);
227 return ok ?[NSData dataWithBytesNoCopy: result.Data length: outputLength freeWhenDone: YES] :nil;
231 - (CSSM_CC_HANDLE) _createSignatureContext: (CSSM_ALGORITHMS)algorithm {
232 const CSSM_ACCESS_CREDENTIALS *credentials;
233 credentials = [self cssmCredentialsForOperation: CSSM_ACL_AUTHORIZATION_SIGN
234 type: kSecCredentialTypeDefault
237 CSSM_CC_HANDLE ccHandle = 0;
238 if (checkcssm(CSSM_CSP_CreateSignatureContext(self.cssmCSPHandle,
243 @"CSSM_CSP_CreateSignatureContext") )
249 - (CSSM_CC_HANDLE) _createPassThroughContext
251 CSSM_CC_HANDLE ccHandle = 0;
252 if (checkcssm(CSSM_CSP_CreatePassThroughContext(self.cssmCSPHandle, self.cssmKey, &ccHandle),
253 @"CSSM_CSP_CreatePassThroughContext") )
262 #endif MYCRYPTO_USE_IPHONE_API
267 Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
269 Redistribution and use in source and binary forms, with or without modification, are permitted
270 provided that the following conditions are met:
272 * Redistributions of source code must retain the above copyright notice, this list of conditions
273 and the following disclaimer.
274 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
275 and the following disclaimer in the documentation and/or other materials provided with the
278 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
279 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
280 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
281 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
282 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
283 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
284 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
285 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.