1.1 --- a/MYSymmetricKey.m Sat Apr 18 18:12:06 2009 -0700
1.2 +++ b/MYSymmetricKey.m Sun Apr 19 00:01:41 2009 -0700
1.3 @@ -15,9 +15,15 @@
1.4 #import <Security/cssmtype.h>
1.5
1.6
1.7 -static const CSSM_ALGORITHMS kCSSMAlgorithms[] = {
1.8 - CSSM_ALGID_AES, CSSM_ALGID_DES, CSSM_ALGID_3DES_3KEY, CSSM_ALGID_CAST, CSSM_ALGID_RC4
1.9 -};
1.10 +CSSM_ALGORITHMS CSSMFromCCAlgorithm( CCAlgorithm ccAlgorithm ) {
1.11 + static const CSSM_ALGORITHMS kCSSMAlgorithms[] = {
1.12 + CSSM_ALGID_AES, CSSM_ALGID_DES, CSSM_ALGID_3DES_3KEY, CSSM_ALGID_CAST, CSSM_ALGID_RC4
1.13 + };
1.14 + if (ccAlgorithm >=0 && ccAlgorithm <= kCCAlgorithmRC4)
1.15 + return kCSSMAlgorithms[ccAlgorithm];
1.16 + else
1.17 + return CSSM_ALGID_NONE;
1.18 +}
1.19
1.20 static const char *kCCAlgorithmNames[] = {"AES", "DES", "DES^3", "CAST", "RC4"};
1.21
1.22 @@ -28,6 +34,8 @@
1.23
1.24 static CSSM_KEY* cssmKeyFromData( NSData *keyData, CSSM_ALGORITHMS algorithm,
1.25 MYKeychain *keychain);
1.26 +//static CSSM_ENCRYPT_MODE defaultModeForAlgorithm(CSSM_ALGORITHMS algorithm);
1.27 +//CSSM_PADDING defaultPaddingForAlgorithm(CSSM_ALGORITHMS algorithm);
1.28 static CSSM_DATA makeSalt( id salty, size_t length );
1.29 static CSSM_RETURN impExpCreatePassKey(
1.30 const SecKeyImportExportParameters *keyParams, // required
1.31 @@ -66,7 +74,7 @@
1.32 {
1.33 Assert(algorithm <= kCCAlgorithmRC4);
1.34 Assert(keyData);
1.35 - CSSM_KEY *key = cssmKeyFromData(keyData, kCSSMAlgorithms[algorithm], keychain);
1.36 + CSSM_KEY *key = cssmKeyFromData(keyData, CSSMFromCCAlgorithm(algorithm), keychain);
1.37 if (!key) {
1.38 [self release];
1.39 return nil;
1.40 @@ -87,11 +95,15 @@
1.41 Assert(algorithm <= kCCAlgorithmRC4);
1.42 CSSM_KEYATTR_FLAGS flags = CSSM_KEYATTR_EXTRACTABLE;
1.43 if (keychain)
1.44 - flags |= CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_EXTRACTABLE;
1.45 + flags |= CSSM_KEYATTR_PERMANENT; // | CSSM_KEYATTR_SENSITIVE; //FIX: Re-enable this bit
1.46 + else {
1.47 + flags |= CSSM_KEYATTR_RETURN_REF;
1.48 + keychain = [MYKeychain defaultKeychain]; // establish a context for the key
1.49 + }
1.50 CSSM_KEYUSE usage = CSSM_KEYUSE_ANY;
1.51 SecKeyRef keyRef = NULL;
1.52 - if (!check(SecKeyGenerate(keychain.keychainRefOrDefault, // nil kc generates a transient key
1.53 - kCSSMAlgorithms[algorithm],
1.54 + if (!check(SecKeyGenerate(keychain.keychainRefOrDefault,
1.55 + CSSMFromCCAlgorithm(algorithm),
1.56 keySizeInBits,
1.57 0, usage, flags, NULL, &keyRef),
1.58 @"SecKeyGenerate")) {
1.59 @@ -211,54 +223,43 @@
1.60
1.61
1.62 #if !TARGET_OS_IPHONE
1.63 -- (NSData*) exportKeyInFormat: (SecExternalFormat)format
1.64 - withPEM: (BOOL)withPEM
1.65 +- (NSData*) exportWrappedKeyWithPassphrasePrompt: (NSString*)prompt
1.66 {
1.67 - if (format==kSecFormatRawKey || format==kSecFormatUnknown)
1.68 - return [super exportKeyInFormat: format withPEM: withPEM];
1.69 -
1.70 - // Get access credentials:
1.71 - const CSSM_ACCESS_CREDENTIALS *credentials;
1.72 - credentials = [self cssmCredentialsForOperation: CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
1.73 - type: kSecCredentialTypeDefault
1.74 - error: nil];
1.75 - if (!credentials)
1.76 - return nil;
1.77 -
1.78 // Prompt use for a passphrase to use for the wrapping key:
1.79 - MYSymmetricKey *wrappingKey = [MYSymmetricKey generateFromUserPassphraseWithAlertTitle: @"Export Key" alertPrompt: @"Enter a passphrase to encrypt the key you're exporting from the Keychain:" creating: YES
1.80 - salt: [MYCryptor randomKeyOfLength: PKCS5_V2_SALT_LEN*8]];
1.81 + MYSymmetricKey *wrappingKey = [MYSymmetricKey
1.82 + generateFromUserPassphraseWithAlertTitle: @"Export Key"
1.83 + alertPrompt: prompt
1.84 + creating: YES
1.85 + salt: [MYCryptor randomKeyOfLength: PKCS5_V2_SALT_LEN*8]];
1.86 if (!wrappingKey)
1.87 return nil;
1.88 + Log(@"Wrapping using %@",wrappingKey);
1.89
1.90 // Create the context:
1.91 + CSSM_ACCESS_CREDENTIALS credentials = {};
1.92 CSSM_CSP_HANDLE cspHandle = self.cssmCSPHandle;
1.93 + //CSSM_ALGORITHMS algorithm = wrappingKey.cssmAlgorithm;
1.94 CSSM_CC_HANDLE ctx;
1.95 if (!checkcssm(CSSM_CSP_CreateSymmetricContext(cspHandle,
1.96 - CSSM_ALGID_NONE,
1.97 - CSSM_ALGMODE_WRAP,
1.98 - NULL,
1.99 + wrappingKey.cssmAlgorithm, //CSSM_ALGID_3DES_3KEY_EDE, //algorithm,
1.100 + CSSM_ALGMODE_CBCPadIV8, //defaultModeForAlgorithm(algorithm),
1.101 + &credentials,
1.102 wrappingKey.cssmKey,
1.103 NULL,
1.104 - CSSM_PADDING_NONE,
1.105 + CSSM_PADDING_PKCS7, //defaultPaddingForAlgorithm(algorithm),
1.106 NULL,
1.107 &ctx),
1.108 @"CSSM_CSP_CreateSymmetricContext"))
1.109 return nil;
1.110
1.111 - // Set the wrapped key format:
1.112 + // Now wrap the key:
1.113 NSData *result = nil;
1.114 - CSSM_CONTEXT_ATTRIBUTE attr = { CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, sizeof(uint32) };
1.115 - attr.Attribute.Uint32 = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7;
1.116 - if (checkcssm(CSSM_UpdateContextAttributes(ctx, 1, &attr), @"CSSM_UpdateContextAttributes")) {
1.117 - // Now wrap the key:
1.118 - CSSM_WRAP_KEY wrappedKey = {};
1.119 - if (checkcssm(CSSM_WrapKey(ctx, credentials, self.cssmKey, NULL, &wrappedKey),
1.120 - @"CSSM_WrapKey")) {
1.121 - // ...and copy the wrapped key data to the result NSData:
1.122 - result = [NSData dataWithBytes: wrappedKey.KeyData.Data length: wrappedKey.KeyData.Length];
1.123 - CSSM_FreeKey(cspHandle, credentials, &wrappedKey, NO);
1.124 - }
1.125 + CSSM_WRAP_KEY wrappedKey = {};
1.126 + if (checkcssm(CSSM_WrapKey(ctx, &credentials, self.cssmKey, NULL, &wrappedKey),
1.127 + @"CSSM_WrapKey")) {
1.128 + // ...and copy the wrapped key data to the result NSData:
1.129 + result = [NSData dataWithBytes: wrappedKey.KeyData.Data length: wrappedKey.KeyData.Length];
1.130 + CSSM_FreeKey(cspHandle, &credentials, &wrappedKey, NO);
1.131 }
1.132 // Finally, delete the context
1.133 CSSM_DeleteContext(ctx);
1.134 @@ -413,7 +414,62 @@
1.135 }
1.136
1.137
1.138 -// Copied from SecImportExportUtils.cpp in Apple's libsecurity_keychain project
1.139 +#pragma mark -
1.140 +// Code from Keychain.framework:
1.141 +#if 0
1.142 +static CSSM_ENCRYPT_MODE defaultModeForAlgorithm(CSSM_ALGORITHMS algorithm) {
1.143 + switch(algorithm) {
1.144 + // 8-byte block ciphers
1.145 + case CSSM_ALGID_DES:
1.146 + case CSSM_ALGID_3DES_3KEY_EDE:
1.147 + case CSSM_ALGID_RC5:
1.148 + case CSSM_ALGID_RC2:
1.149 + return CSSM_ALGMODE_CBCPadIV8; break;
1.150 + // 16-byte block ciphers
1.151 + case CSSM_ALGID_AES:
1.152 + return CSSM_ALGMODE_CBCPadIV8; break;
1.153 + // stream ciphers
1.154 + case CSSM_ALGID_ASC:
1.155 + case CSSM_ALGID_RC4:
1.156 + return CSSM_ALGMODE_NONE; break;
1.157 + // Unknown
1.158 + default:
1.159 + Warn(@"Asked for the default mode for algorithm %d, but don't know that algorithm.\n", algorithm);
1.160 + return CSSM_ALGMODE_NONE;
1.161 + }
1.162 +}
1.163 +
1.164 +CSSM_PADDING defaultPaddingForAlgorithm(CSSM_ALGORITHMS algorithm) {
1.165 + switch(algorithm) {
1.166 + /* 8-byte block ciphers */
1.167 + case CSSM_ALGID_DES:
1.168 + case CSSM_ALGID_3DES_3KEY_EDE:
1.169 + case CSSM_ALGID_RC5:
1.170 + case CSSM_ALGID_RC2:
1.171 + return CSSM_PADDING_PKCS5; break;
1.172 + /* 16-byte block ciphers */
1.173 + case CSSM_ALGID_AES:
1.174 + return CSSM_PADDING_PKCS7; break;
1.175 + /* stream ciphers */
1.176 + case CSSM_ALGID_ASC:
1.177 + case CSSM_ALGID_RC4:
1.178 + return CSSM_PADDING_NONE; break;
1.179 + /* RSA/DSA asymmetric */
1.180 + case CSSM_ALGID_DSA:
1.181 + case CSSM_ALGID_RSA:
1.182 + return CSSM_PADDING_PKCS1; break;
1.183 + /* Unknown */
1.184 + default:
1.185 + Warn(@"Asked for the default padding mode for %d, but don't know that algorithm.\n", algorithm);
1.186 + return CSSM_PADDING_NONE;
1.187 + }
1.188 +}
1.189 +#endif
1.190 +
1.191 +#pragma mark -
1.192 +// Code below was copied from SecImportExportUtils.cpp in Apple's libsecurity_keychain project
1.193 +
1.194 +
1.195 /*
1.196 * Given a context specified via a CSSM_CC_HANDLE, add a new
1.197 * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType,