Implemented wrap/unwrap of session key using a key-pair.
2 // MYSymmetricKey-iPhone.m
5 // Created by Jens Alfke on 4/17/09.
6 // Copyright 2009 Jens Alfke. All rights reserved.
9 #import "MYSymmetricKey.h"
11 #import "MYCrypto_Private.h"
13 #if MYCRYPTO_USE_IPHONE_API
16 typedef uint32_t CSSM_ALGORITHMS;
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,
29 static const CSSM_ALGORITHMS kCSSMAlgorithms[] = {
30 CSSM_ALGID_AES, CSSM_ALGID_DES, CSSM_ALGID_3DES_3KEY, CSSM_ALGID_CAST, CSSM_ALGID_RC4
33 static const char *kCCAlgorithmNames[] = {"AES", "DES", "DES^3", "CAST", "RC4"};
36 @implementation MYSymmetricKey
39 - (id) _initWithKeyData: (NSData*)keyData
40 algorithm: (CCAlgorithm)algorithm
41 inKeychain: (MYKeychain*)keychain
43 Assert(algorithm <= kCCAlgorithmRC4);
45 NSNumber *keySizeInBits = [NSNumber numberWithUnsignedInt: keyData.length * 8];
46 NSDictionary *keyAttrs = $dict( {(id)kSecClass, (id)kSecClassKey},
47 //{(id)kSecAttrKeyClass, (id)kSecAttrKeyClassSymmetric},
48 {(id)kSecAttrKeyType, [NSNumber numberWithUnsignedInt: kCSSMAlgorithms[algorithm]]},
49 {(id)kSecAttrKeySizeInBits, keySizeInBits},
50 {(id)kSecAttrEffectiveKeySize, keySizeInBits},
51 {(id)kSecAttrIsPermanent, keychain ?$true :$false},
52 {(id)kSecAttrCanEncrypt, $true},
53 {(id)kSecAttrCanDecrypt, $true},
54 {(id)kSecAttrCanWrap, $false},
55 {(id)kSecAttrCanUnwrap, $false},
56 {(id)kSecAttrCanDerive, $false},
57 {(id)kSecAttrCanSign, $false},
58 {(id)kSecAttrCanVerify, $false},
59 {(id)kSecValueData, keyData},
60 {(id)kSecReturnPersistentRef, $true});
61 SecKeyRef keyRef = NULL;
62 if (!check(SecItemAdd((CFDictionaryRef)keyAttrs, (CFTypeRef*)&keyRef), @"SecItemAdd")) {
66 Assert(keyRef, @"SecItemAdd didn't return anything");
67 self = [self initWithKeyRef: keyRef];
72 - (id) initWithKeyData: (NSData*)keyData
73 algorithm: (CCAlgorithm)algorithm
75 return [self _initWithKeyData: keyData algorithm: algorithm inKeychain: nil];
78 + (MYSymmetricKey*) _generateSymmetricKeyOfSize: (unsigned)keySizeInBits
79 algorithm: (CCAlgorithm)algorithm
80 inKeychain: (MYKeychain*)keychain
82 return [[[self alloc] _initWithKeyData: [MYCryptor randomKeyOfLength: keySizeInBits]
88 + (MYSymmetricKey*) generateSymmetricKeyOfSize: (unsigned)keySizeInBits
89 algorithm: (CCAlgorithm)algorithm {
90 return [self _generateSymmetricKeyOfSize: keySizeInBits
96 - (SecExternalItemType) keyType {
97 return kSecAttrKeyClassSymmetric;
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];
107 return kCCAlgorithmAES128;
109 return kCCAlgorithmDES;
110 case CSSM_ALGID_3DES_3KEY:
111 return kCCAlgorithm3DES;
112 case CSSM_ALGID_CAST:
113 return kCCAlgorithmCAST;
115 return kCCAlgorithmRC4;
117 Warn(@"CSSM_ALGORITHMS #%u doesn't map to any CCAlgorithm", cssmAlg);
118 return (CCAlgorithm)-1;
122 - (const char*) algorithmName {
123 CCAlgorithm a = self.algorithm;
124 if (a >= 0 && a <= kCCAlgorithmRC4)
125 return kCCAlgorithmNames[a];
130 - (unsigned) keySizeInBits {
131 id keySize = [self _attribute: kSecAttrKeySizeInBits];
132 Assert(keySize!=nil, @"Key has no kSecAttrKeySizeInBits");
133 return [keySize unsignedIntValue];
137 - (NSString*) description {
138 return $sprintf(@"%@[%u-bit %s]", [self class], self.keySizeInBits, self.algorithmName);
142 - (NSData*) _cryptData: (NSData*)data operation: (CCOperation)op options: (CCOptions)options
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,
153 Warn(@"MYSymmetricKey: CCCrypt returned error %i",status);
156 output.length = bytesWritten;
160 - (NSData*) encryptData: (NSData*)data {
161 return [self _cryptData: data operation: kCCEncrypt options: kCCOptionPKCS7Padding];
165 - (NSData*) decryptData: (NSData*)data {
166 return [self _cryptData: data operation: kCCDecrypt options: kCCOptionPKCS7Padding];
173 #endif MYCRYPTO_USE_IPHONE_API