MYSymmetricKey.m
changeset 13 6fd9177eb6da
parent 12 e4c971be4079
child 14 3af1d1c0ceb5
     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,