MYSymmetricKey-iPhone.m
author Jens Alfke <jens@mooseyard.com>
Tue Jun 09 23:58:03 2009 -0700 (2009-06-09)
changeset 24 6856e071d25a
parent 14 3af1d1c0ceb5
child 26 d9c2a06d4e4e
permissions -rw-r--r--
* More work on iPhone compatibility.
* Restored the signature-verification code to MYCertInfo, which I'd removed earlier. I now need it to verify self-signed certs, since the Security framework won't do it for me.
* Merged MYCertificate-iPhone.m into MYCertificate.m since there's more shared code now.
     1 //
     2 //  MYSymmetricKey-iPhone.m
     3 //  MYCrypto
     4 //
     5 //  Created by Jens Alfke on 4/17/09.
     6 //  Copyright 2009 Jens Alfke. All rights reserved.
     7 //
     8 
     9 #import "MYSymmetricKey.h"
    10 #import "MYCryptor.h"
    11 #import "MYCrypto_Private.h"
    12 
    13 #if MYCRYPTO_USE_IPHONE_API
    14 
    15 
    16 typedef uint32_t CSSM_ALGORITHMS;
    17 enum {
    18 // Taken from cssmtype.h in OS X 10.5 SDK:
    19 	CSSM_ALGID_NONE =					0x00000000L,
    20 	CSSM_ALGID_DES =					CSSM_ALGID_NONE + 14,
    21 	CSSM_ALGID_3DES_3KEY_EDE =			CSSM_ALGID_NONE + 17,
    22 	CSSM_ALGID_3DES_3KEY =           	CSSM_ALGID_3DES_3KEY_EDE,
    23 	CSSM_ALGID_RC4 =					CSSM_ALGID_NONE + 25,
    24 	CSSM_ALGID_CAST =					CSSM_ALGID_NONE + 27,
    25 	CSSM_ALGID_VENDOR_DEFINED =			CSSM_ALGID_NONE + 0x80000000L,
    26 	CSSM_ALGID_AES
    27 };
    28 
    29 static const CSSM_ALGORITHMS kCSSMAlgorithms[] = {
    30 CSSM_ALGID_AES, CSSM_ALGID_DES, CSSM_ALGID_3DES_3KEY, CSSM_ALGID_CAST, CSSM_ALGID_RC4
    31 };
    32 
    33 static const char *kCCAlgorithmNames[] = {"AES", "DES", "DES^3", "CAST", "RC4"};
    34 
    35 
    36 @implementation MYSymmetricKey
    37 
    38 
    39 - (id) _initWithKeyData: (NSData*)keyData
    40               algorithm: (CCAlgorithm)algorithm
    41              inKeychain: (MYKeychain*)keychain
    42 {
    43     Assert(algorithm <= kCCAlgorithmRC4);
    44     Assert(keyData);
    45     NSNumber *keySizeInBits = [NSNumber numberWithUnsignedInt: keyData.length * 8];
    46     NSNumber *keyType = [NSNumber numberWithUnsignedInt: kCSSMAlgorithms[algorithm]];
    47     NSMutableDictionary *keyAttrs = $mdict( {(id)kSecClass, (id)kSecClassKey},
    48                                             {(id)kSecAttrKeyClass, (id)kSecAttrKeyClassSymmetric},
    49                                             {(id)kSecAttrKeyType, keyType},
    50                                             {(id)kSecValueData, keyData},
    51                                             {(id)kSecAttrKeySizeInBits, keySizeInBits},
    52                                             {(id)kSecAttrEffectiveKeySize, keySizeInBits},
    53                                             {(id)kSecAttrIsPermanent, keychain ?$true :$false},
    54                                             {(id)kSecAttrCanEncrypt, $true},
    55                                             {(id)kSecAttrCanDecrypt, $true},
    56                                             {(id)kSecAttrCanWrap, $false},
    57                                             {(id)kSecAttrCanUnwrap, $false},
    58                                             {(id)kSecAttrCanDerive, $false},
    59                                             {(id)kSecAttrCanSign, $false},
    60                                             {(id)kSecAttrCanVerify, $false},
    61                                             {(id)kSecReturnPersistentRef, $true});
    62     SecKeyRef keyRef = [[self class] _addKeyWithInfo: keyAttrs];
    63     if (!keyRef) {
    64         [self release];
    65         return nil;
    66     }
    67     self = [self initWithKeyRef: keyRef];
    68     CFRelease(keyRef);
    69     return self;
    70 }
    71 
    72 - (id) initWithKeyData: (NSData*)keyData
    73              algorithm: (CCAlgorithm)algorithm
    74 {
    75     return [self _initWithKeyData: keyData algorithm: algorithm inKeychain: nil];
    76 }
    77 
    78 + (MYSymmetricKey*) _generateSymmetricKeyOfSize: (unsigned)keySizeInBits
    79                                       algorithm: (CCAlgorithm)algorithm
    80                                      inKeychain: (MYKeychain*)keychain
    81 {
    82     return [[[self alloc] _initWithKeyData: [MYCryptor randomKeyOfLength: keySizeInBits]
    83                                  algorithm: algorithm
    84                                 inKeychain: keychain]
    85                     autorelease];
    86 }
    87 
    88 + (MYSymmetricKey*) generateSymmetricKeyOfSize: (unsigned)keySizeInBits
    89                                      algorithm: (CCAlgorithm)algorithm {
    90     return [self _generateSymmetricKeyOfSize: keySizeInBits
    91                                    algorithm: algorithm
    92                                   inKeychain: nil];
    93 }
    94 
    95 
    96 - (SecExternalItemType) keyClass {
    97     return kSecAttrKeyClassSymmetric;
    98 }
    99 
   100 - (CCAlgorithm) algorithm {
   101     CSSM_ALGORITHMS cssmAlg;
   102     id keyType = [self _attribute: kSecAttrKeyType];
   103     Assert(keyType!=nil, @"Key has no kSecAttrKeyType");
   104     cssmAlg = [keyType unsignedIntValue];
   105     switch(cssmAlg) {
   106         case CSSM_ALGID_AES:
   107             return kCCAlgorithmAES128;
   108         case CSSM_ALGID_DES:
   109             return kCCAlgorithmDES;	
   110         case CSSM_ALGID_3DES_3KEY:
   111             return kCCAlgorithm3DES;
   112         case CSSM_ALGID_CAST:
   113             return kCCAlgorithmCAST;
   114         case CSSM_ALGID_RC4:
   115             return kCCAlgorithmRC4;	
   116         default:
   117             Warn(@"CSSM_ALGORITHMS #%u doesn't map to any CCAlgorithm", cssmAlg);
   118             return (CCAlgorithm)-1;
   119     }
   120 }
   121 
   122 - (const char*) algorithmName {
   123     CCAlgorithm a = self.algorithm;
   124     if (a >= 0 && a <= kCCAlgorithmRC4)
   125         return kCCAlgorithmNames[a];
   126     else
   127         return "???";
   128 }
   129 
   130 - (unsigned) keySizeInBits {
   131     id keySize = [self _attribute: kSecAttrKeySizeInBits];
   132     Assert(keySize!=nil, @"Key has no kSecAttrKeySizeInBits");
   133     return [keySize unsignedIntValue];
   134 }
   135 
   136 
   137 - (NSString*) description {
   138     return $sprintf(@"%@[%u-bit %s]", [self class], self.keySizeInBits, self.algorithmName);
   139 }
   140 
   141 
   142 - (NSData*) _cryptData: (NSData*)data operation: (CCOperation)op options: (CCOptions)options
   143 {
   144     NSData *keyData = self.keyData;
   145     Assert(keyData, @"Couldn't get key data");
   146     NSMutableData *output = [NSMutableData dataWithLength: data.length + 256];
   147     size_t bytesWritten = 0;
   148     CCCryptorStatus status = CCCrypt(op, self.algorithm, options, 
   149                                      keyData.bytes, keyData.length, NULL,
   150                                      data.bytes, data.length, output.mutableBytes, output.length,
   151                                      &bytesWritten);
   152     if (status) {
   153         Warn(@"MYSymmetricKey: CCCrypt returned error %i",status);
   154         return nil;
   155     }
   156     output.length = bytesWritten;
   157     return output;
   158 }
   159 
   160 - (NSData*) encryptData: (NSData*)data {
   161     return [self _cryptData: data operation: kCCEncrypt options: kCCOptionPKCS7Padding];
   162 }
   163 
   164 
   165 - (NSData*) decryptData: (NSData*)data {
   166     return [self _cryptData: data operation: kCCDecrypt options: kCCOptionPKCS7Padding];
   167 }
   168 
   169 
   170 @end
   171 
   172 
   173 #endif MYCRYPTO_USE_IPHONE_API
   174 
   175 
   176 
   177 /*
   178  Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
   179  
   180  Redistribution and use in source and binary forms, with or without modification, are permitted
   181  provided that the following conditions are met:
   182  
   183  * Redistributions of source code must retain the above copyright notice, this list of conditions
   184  and the following disclaimer.
   185  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   186  and the following disclaimer in the documentation and/or other materials provided with the
   187  distribution.
   188  
   189  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
   190  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
   191  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
   192  BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   193  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
   194   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   195  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
   196  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   197  */