]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-key-helpers.h
Security-58286.200.222.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / regressions / kc-key-helpers.h
1 /*
2 * Copyright (c) 2016 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #ifndef kc_key_helpers_h
25 #define kc_key_helpers_h
26
27 #include "kc-helpers.h"
28 #include "utilities/SecCFRelease.h"
29
30 #if TARGET_OS_MAC
31
32 #pragma clang diagnostic push
33 #pragma clang diagnostic ignored "-Wunused-variable"
34 #pragma clang diagnostic ignored "-Wunused-function"
35
36 static CFMutableDictionaryRef makeBaseKeyDictionary() {
37 CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
38 CFDictionarySetValue(query, kSecClass, kSecClassKey);
39 return query;
40 }
41
42 static CFMutableDictionaryRef createQueryKeyDictionary(SecKeychainRef kc, CFStringRef keyClass) {
43 CFMutableDictionaryRef query = makeBaseKeyDictionary();
44
45 CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
46 CFArrayAppendValue((CFMutableArrayRef)searchList, kc);
47 CFDictionarySetValue(query, kSecMatchSearchList, searchList);
48
49 CFDictionarySetValue(query, kSecAttrKeyClass, keyClass);
50
51 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
52 return query;
53 }
54
55 static CFMutableDictionaryRef createQueryKeyDictionaryWithLabel(SecKeychainRef kc, CFStringRef keyClass, CFStringRef label) {
56 CFMutableDictionaryRef query = createQueryKeyDictionary(kc, keyClass);
57 CFDictionarySetValue(query, kSecAttrLabel, label);
58 return query;
59 }
60
61 static CFMutableDictionaryRef createAddKeyDictionaryWithApplicationLabel(SecKeychainRef kc, CFStringRef keyClass, CFStringRef label, CFStringRef applicationLabel) {
62 CFMutableDictionaryRef query = makeBaseKeyDictionary();
63 CFDictionaryAddValue(query, kSecUseKeychain, kc);
64
65 CFDictionarySetValue(query, kSecAttrLabel, label);
66 if(applicationLabel) {
67 CFDictionarySetValue(query, kSecAttrApplicationLabel, applicationLabel);
68 } else {
69 CFDictionarySetValue(query, kSecAttrApplicationLabel, CFSTR("test_application")); // without setting this, it uses the current datetime.
70 }
71
72 int32_t n = 0;
73 if(CFEqual(keyClass, kSecAttrKeyClassSymmetric)) {
74 CFDictionarySetValue(query, kSecAttrKeyType, kSecAttrKeyTypeAES);
75 n = 128;
76 } else if(CFEqual(keyClass, kSecAttrKeyClassPublic) ||
77 CFEqual(keyClass, kSecAttrKeyClassPrivate)) {
78 CFDictionarySetValue(query, kSecAttrKeyType, kSecAttrKeyTypeRSA);
79 n = 1024;
80 }
81 CFNumberRef num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &n);
82 CFDictionarySetValue(query, kSecAttrKeySizeInBits, num);
83 CFReleaseNull(num);
84
85 return query;
86 }
87 static CFMutableDictionaryRef createAddKeyDictionary(SecKeychainRef kc, CFStringRef keyClass, CFStringRef label) {
88 return createAddKeyDictionaryWithApplicationLabel(kc, keyClass, label, NULL);
89 }
90
91 static SecKeyRef createCustomKeyWithApplicationLabel(const char* name, SecKeychainRef kc, CFStringRef label, CFStringRef applicationLabel) {
92 CFMutableDictionaryRef query = createAddKeyDictionaryWithApplicationLabel(kc, kSecAttrKeyClassSymmetric, label, applicationLabel);
93
94 CFErrorRef error = NULL;
95 SecKeyRef item = SecKeyGenerateSymmetric(query, &error);
96 ok(item != NULL, "%s: SecKeyGenerateSymmetric: %ld", name, error ? CFErrorGetCode(error) : 0);
97
98 CFReleaseNull(query);
99 return item;
100 }
101 #define createCustomKeyWithApplicationLabelTests 1
102
103 static SecKeyRef createCustomKey(const char* name, SecKeychainRef kc, CFStringRef label) {
104 return createCustomKeyWithApplicationLabel(name, kc, label, NULL);
105 }
106 #define createCustomKeyTests createCustomKeyWithApplicationLabelTests
107
108 static SecKeyRef makeKey(const char* name, SecKeychainRef kc) {
109 return createCustomKey(name, kc, CFSTR("test_key"));
110 }
111 #define makeKeyTests createCustomKeyTests
112
113 static void makeCustomKeyPair(const char* name, SecKeychainRef kc, CFStringRef label, SecKeyRef* aPub, SecKeyRef* aPriv) {
114 CFMutableDictionaryRef query = createAddKeyDictionary(kc, kSecAttrKeyClassPublic, label);
115
116 SecKeyRef pub;
117 SecKeyRef priv;
118 ok_status(SecKeyGeneratePair(query, &pub, &priv), "%s: SecKeyGeneratePair returned a result", name);
119
120 if(aPub) {
121 *aPub = pub;
122 }
123 if(aPriv) {
124 *aPriv = priv;
125 }
126
127 CFReleaseNull(query);
128 }
129 #define makeCustomKeyPairTests 1
130
131 static void makeKeyPair(const char* name, SecKeychainRef kc, SecKeyRef* aPub, SecKeyRef* aPriv) {
132 makeCustomKeyPair(name, kc, CFSTR("test_key"), aPub, aPriv);
133 }
134 #define makeKeyPairTests makeCustomKeyPairTests
135
136 // This only works for symmetric keys; key pairs cannot ever generate a duplicate (due to setting kSecKeyLabel to the hash of the public key)
137 static void makeCustomDuplicateKey(const char* name, SecKeychainRef kc, CFStringRef label) {
138 CFMutableDictionaryRef query;
139
140 query = createAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label);
141 CFErrorRef error = NULL;
142 CFReleaseSafe(SecKeyGenerateSymmetric(query, &error));
143 is(CFErrorGetCode(error), errSecDuplicateItem, "%s: SecKeyGenerateSymmetric (duplicate) errored: %ld", name, error ? CFErrorGetCode(error) : -1);
144
145 CFReleaseNull(query);
146 }
147 #define makeCustomDuplicateKeyTests 1
148
149 static void makeDuplicateKey(const char* name, SecKeychainRef kc) {
150 makeCustomDuplicateKey(name, kc, CFSTR("test_key"));
151 }
152 #define makeDuplicateKeyTests makeCustomDuplicateKeyTests
153
154 static SecKeyRef makeCustomFreeKey(const char* name, SecKeychainRef kc, CFStringRef label) {
155 SecKeyRef symkey;
156
157 ok_status(SecKeyGenerate(
158 NULL,
159 CSSM_ALGID_AES, 128,
160 0, /* contextHandle */
161 CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
162 CSSM_KEYATTR_EXTRACTABLE,
163 NULL, /* initialAccess */
164 &symkey), "%s: SecKeyGenerate", name);;
165
166 CFMutableDictionaryRef query = createAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label);
167
168 CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
169 CFArrayAppendValue((CFMutableArrayRef)itemList, symkey);
170
171 CFDictionarySetValue(query, kSecUseItemList, itemList);
172
173 CFTypeRef result = NULL;
174 ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name);
175 ok(result != NULL, "%s: SecItemAdd returned a result", name);
176 CFReleaseNull(symkey);
177 return (SecKeyRef) result;
178 }
179 #define makeCustomFreeKeyTests 3
180
181 static SecKeyRef makeFreeKey(const char* name, SecKeychainRef kc) {
182 return makeCustomFreeKey(name, kc, CFSTR("test_free_key"));
183 }
184 #define makeFreeKeyTests makeCustomFreeKeyTests
185
186 static SecKeyRef makeCustomDuplicateFreeKey(const char* name, SecKeychainRef kc, CFStringRef label) {
187 SecKeyRef symkey;
188
189 ok_status(SecKeyGenerate(
190 NULL,
191 CSSM_ALGID_AES, 128,
192 0, /* contextHandle */
193 CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
194 CSSM_KEYATTR_EXTRACTABLE,
195 NULL, /* initialAccess */
196 &symkey), "%s: SecKeyGenerate", name);;
197
198 CFMutableDictionaryRef query = createAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label);
199
200 CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
201 CFArrayAppendValue((CFMutableArrayRef)itemList, symkey);
202
203 CFDictionarySetValue(query, kSecUseItemList, itemList);
204
205 CFTypeRef result = NULL;
206 is(SecItemAdd(query, &result), errSecDuplicateItem, "%s: SecItemAdd (duplicate)", name);
207 CFReleaseNull(symkey);
208 return (SecKeyRef) result;
209 }
210 #define makeCustomDuplicateFreeKeyTests 2
211
212 static SecKeyRef makeDuplicateFreeKey(const char* name, SecKeychainRef kc) {
213 return makeCustomFreeKey(name, kc, CFSTR("test_free_key"));
214 }
215 #define makeDuplicateFreeKeyTests makeCustomDuplicateFreeKeyTests
216
217 #define checkKeyUseTests 4
218 static void checkKeyUse(SecKeyRef key, OSStatus expectedStatus) {
219 CFStringRef plaintext = CFSTR("A short story: the string goes into the encryptor, and returns unrecognizable. The decryptor reverses.");
220 CFDataRef plaintextData = CFDataCreate(NULL, (uint8_t*) CFStringGetCStringPtr(plaintext, kCFStringEncodingUTF8), CFStringGetLength(plaintext));
221
222 /* encrypt first */
223 SecTransformRef transform = SecEncryptTransformCreate(key, NULL);
224 SecTransformSetAttribute(transform, kSecPaddingKey, kSecPaddingPKCS7Key, NULL);
225 SecTransformSetAttribute(transform, kSecEncryptionMode, kSecModeCBCKey, NULL);
226 SecTransformSetAttribute(transform, kSecTransformInputAttributeName, plaintextData, NULL);
227
228 CFErrorRef error = NULL;
229 CFDataRef ciphertextData = SecTransformExecute(transform, &error);
230
231 if(error) {
232 is(CFErrorGetCode(error), expectedStatus, "%s: Encrypting data failed: %d %s (and expected %d)", testName, (int) CFErrorGetCode(error), CFStringGetCStringPtr(CFErrorCopyDescription(error), kCFStringEncodingUTF8), (int) expectedStatus);
233
234 if(expectedStatus != errSecSuccess) {
235 // make test numbers match and quit
236 for(int i = 1; i < checkKeyUseTests; i++) {
237 pass("test numbers match");
238 }
239 return;
240 }
241
242 } else {
243 pass("%s: transform executed", testName);
244 }
245
246 CFReleaseSafe(transform);
247
248 /* and now decrypt */
249 transform = SecDecryptTransformCreate(key, NULL);
250 SecTransformSetAttribute(transform, kSecPaddingKey, kSecPaddingPKCS7Key, NULL);
251 SecTransformSetAttribute(transform, kSecEncryptionMode, kSecModeCBCKey, NULL);
252 SecTransformSetAttribute(transform, kSecTransformInputAttributeName, ciphertextData, NULL);
253
254 CFDataRef roundtripData = SecTransformExecute(transform, &error);
255 is(error, NULL, "%s: checkKeyUse: SecTransformExecute (decrypt)", testName);
256
257 if(error) {
258 CFStringRef errorStr = CFErrorCopyDescription(error);
259 fail("%s: Decrypting data failed: %d %s", testName, (int) CFErrorGetCode(error), CFStringGetCStringPtr(errorStr, kCFStringEncodingUTF8));
260 CFRelease(errorStr);
261 } else {
262 pass("%s: make test numbers match", testName);
263 }
264
265 CFReleaseSafe(transform);
266
267 eq_cf(plaintextData, roundtripData, "%s: checkKeyUse: roundtripped data is input data", testName);
268
269 CFReleaseSafe(plaintext);
270 CFReleaseSafe(plaintextData);
271 CFReleaseSafe(ciphertextData);
272 CFReleaseSafe(roundtripData);
273 }
274
275
276
277 #pragma clang diagnostic pop
278
279 #else
280
281 #endif /* TARGET_OS_MAC */
282
283
284 #endif /* kc_key_helpers_h */