]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/regressions/kc-key-helpers.h
Security-57740.31.2.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 makeQueryKeyDictionary(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 makeQueryKeyDictionaryWithLabel(SecKeychainRef kc, CFStringRef keyClass, CFStringRef label) {
56 CFMutableDictionaryRef query = makeQueryKeyDictionary(kc, keyClass);
57 CFDictionarySetValue(query, kSecAttrLabel, label);
58 return query;
59 }
60
61 static CFMutableDictionaryRef makeAddKeyDictionaryWithApplicationLabel(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
84 return query;
85 }
86 static CFMutableDictionaryRef makeAddKeyDictionary(SecKeychainRef kc, CFStringRef keyClass, CFStringRef label) {
87 return makeAddKeyDictionaryWithApplicationLabel(kc, keyClass, label, NULL);
88 }
89
90 static SecKeyRef makeCustomKeyWithApplicationLabel(const char* name, SecKeychainRef kc, CFStringRef label, CFStringRef applicationLabel) {
91 CFMutableDictionaryRef query = makeAddKeyDictionaryWithApplicationLabel(kc, kSecAttrKeyClassSymmetric, label, applicationLabel);
92
93 CFErrorRef error = NULL;
94 SecKeyRef item = SecKeyGenerateSymmetric(query, &error);
95 ok(item != NULL, "%s: SecKeyGenerateSymmetric: %ld", name, error ? CFErrorGetCode(error) : 0);
96
97 CFReleaseNull(query);
98 return item;
99 }
100 #define makeCustomKeyWithApplicationLabelTests 1
101
102 static SecKeyRef makeCustomKey(const char* name, SecKeychainRef kc, CFStringRef label) {
103 return makeCustomKeyWithApplicationLabel(name, kc, label, NULL);
104 }
105 #define makeCustomKeyTests makeCustomKeyWithApplicationLabelTests
106
107 static SecKeyRef makeKey(const char* name, SecKeychainRef kc) {
108 return makeCustomKey(name, kc, CFSTR("test_key"));
109 }
110 #define makeKeyTests makeCustomKeyTests
111
112 static void makeCustomKeyPair(const char* name, SecKeychainRef kc, CFStringRef label, SecKeyRef* aPub, SecKeyRef* aPriv) {
113 CFMutableDictionaryRef query = makeAddKeyDictionary(kc, kSecAttrKeyClassPublic, label);
114
115 SecKeyRef pub;
116 SecKeyRef priv;
117 ok_status(SecKeyGeneratePair(query, &pub, &priv), "%s: SecKeyGeneratePair returned a result", name);
118
119 if(aPub) {
120 *aPub = pub;
121 }
122 if(aPriv) {
123 *aPriv = priv;
124 }
125
126 CFReleaseNull(query);
127 }
128 #define makeCustomKeyPairTests 1
129
130 static void makeKeyPair(const char* name, SecKeychainRef kc, SecKeyRef* aPub, SecKeyRef* aPriv) {
131 makeCustomKeyPair(name, kc, CFSTR("test_key"), aPub, aPriv);
132 }
133 #define makeKeyPairTests makeCustomKeyPairTests
134
135 // This only works for symmetric keys; key pairs cannot ever generate a duplicate (due to setting kSecKeyLabel to the hash of the public key)
136 static void makeCustomDuplicateKey(const char* name, SecKeychainRef kc, CFStringRef label) {
137 CFMutableDictionaryRef query;
138
139 query = makeAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label);
140 CFErrorRef error = NULL;
141 CFReleaseSafe(SecKeyGenerateSymmetric(query, &error));
142 is(CFErrorGetCode(error), errSecDuplicateItem, "%s: SecKeyGenerateSymmetric (duplicate) errored: %ld", name, error ? CFErrorGetCode(error) : -1);
143
144 CFReleaseNull(query);
145 }
146 #define makeCustomDuplicateKeyTests 1
147
148 static void makeDuplicateKey(const char* name, SecKeychainRef kc) {
149 makeCustomDuplicateKey(name, kc, CFSTR("test_key"));
150 }
151 #define makeDuplicateKeyTests makeCustomDuplicateKeyTests
152
153 static SecKeyRef makeCustomFreeKey(const char* name, SecKeychainRef kc, CFStringRef label) {
154 SecKeyRef symkey;
155
156 ok_status(SecKeyGenerate(
157 NULL,
158 CSSM_ALGID_AES, 128,
159 0, /* contextHandle */
160 CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
161 CSSM_KEYATTR_EXTRACTABLE,
162 NULL, /* initialAccess */
163 &symkey), "%s: SecKeyGenerate", name);;
164
165 CFMutableDictionaryRef query = makeAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label);
166
167 CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
168 CFArrayAppendValue((CFMutableArrayRef)itemList, symkey);
169
170 CFDictionarySetValue(query, kSecUseItemList, itemList);
171
172 CFTypeRef result = NULL;
173 ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name);
174 ok(result != NULL, "%s: SecItemAdd returned a result", name);
175 CFReleaseNull(symkey);
176 return (SecKeyRef) result;
177 }
178 #define makeCustomFreeKeyTests 3
179
180 static SecKeyRef makeFreeKey(const char* name, SecKeychainRef kc) {
181 return makeCustomFreeKey(name, kc, CFSTR("test_free_key"));
182 }
183 #define makeFreeKeyTests makeCustomFreeKeyTests
184
185 static SecKeyRef makeCustomDuplicateFreeKey(const char* name, SecKeychainRef kc, CFStringRef label) {
186 SecKeyRef symkey;
187
188 ok_status(SecKeyGenerate(
189 NULL,
190 CSSM_ALGID_AES, 128,
191 0, /* contextHandle */
192 CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
193 CSSM_KEYATTR_EXTRACTABLE,
194 NULL, /* initialAccess */
195 &symkey), "%s: SecKeyGenerate", name);;
196
197 CFMutableDictionaryRef query = makeAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label);
198
199 CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
200 CFArrayAppendValue((CFMutableArrayRef)itemList, symkey);
201
202 CFDictionarySetValue(query, kSecUseItemList, itemList);
203
204 CFTypeRef result = NULL;
205 is(SecItemAdd(query, &result), errSecDuplicateItem, "%s: SecItemAdd (duplicate)", name);
206 CFReleaseNull(symkey);
207 return (SecKeyRef) result;
208 }
209 #define makeCustomDuplicateFreeKeyTests 2
210
211 static SecKeyRef makeDuplicateFreeKey(const char* name, SecKeychainRef kc) {
212 return makeCustomFreeKey(name, kc, CFSTR("test_free_key"));
213 }
214 #define makeDuplicateFreeKeyTests makeCustomDuplicateFreeKeyTests
215
216 #define checkKeyUseTests 4
217 static void checkKeyUse(SecKeyRef key, OSStatus expectedStatus) {
218 CFStringRef plaintext = CFSTR("A short story: the string goes into the encryptor, and returns unrecognizable. The decryptor reverses.");
219 CFDataRef plaintextData = CFDataCreate(NULL, (uint8_t*) CFStringGetCStringPtr(plaintext, kCFStringEncodingUTF8), CFStringGetLength(plaintext));
220
221 /* encrypt first */
222 SecTransformRef transform = SecEncryptTransformCreate(key, NULL);
223 SecTransformSetAttribute(transform, kSecPaddingKey, kSecPaddingPKCS7Key, NULL);
224 SecTransformSetAttribute(transform, kSecEncryptionMode, kSecModeCBCKey, NULL);
225 SecTransformSetAttribute(transform, kSecTransformInputAttributeName, plaintextData, NULL);
226
227 CFErrorRef error = NULL;
228 CFDataRef ciphertextData = SecTransformExecute(transform, &error);
229
230 if(error) {
231 is(CFErrorGetCode(error), expectedStatus, "%s: Encrypting data failed: %d %s (and expected %d)", testName, (int) CFErrorGetCode(error), CFStringGetCStringPtr(CFErrorCopyDescription(error), kCFStringEncodingUTF8), (int) expectedStatus);
232
233 if(expectedStatus != errSecSuccess) {
234 // make test numbers match and quit
235 for(int i = 1; i < checkKeyUseTests; i++) {
236 pass("test numbers match");
237 }
238 return;
239 }
240
241 } else {
242 pass("%s: transform executed", testName);
243 }
244
245 CFReleaseSafe(transform);
246
247 /* and now decrypt */
248 transform = SecDecryptTransformCreate(key, NULL);
249 SecTransformSetAttribute(transform, kSecPaddingKey, kSecPaddingPKCS7Key, NULL);
250 SecTransformSetAttribute(transform, kSecEncryptionMode, kSecModeCBCKey, NULL);
251 SecTransformSetAttribute(transform, kSecTransformInputAttributeName, ciphertextData, NULL);
252
253 CFDataRef roundtripData = SecTransformExecute(transform, &error);
254 is(error, NULL, "%s: checkKeyUse: SecTransformExecute (decrypt)", testName);
255
256 if(error) {
257 CFStringRef errorStr = CFErrorCopyDescription(error);
258 fail("%s: Decrypting data failed: %d %s", testName, (int) CFErrorGetCode(error), CFStringGetCStringPtr(errorStr, kCFStringEncodingUTF8));
259 CFRelease(errorStr);
260 } else {
261 pass("%s: make test numbers match", testName);
262 }
263
264 CFReleaseSafe(transform);
265
266 eq_cf(plaintextData, roundtripData, "%s: checkKeyUse: roundtripped data is input data", testName);
267
268 CFReleaseSafe(plaintext);
269 CFReleaseSafe(plaintextData);
270 CFReleaseSafe(ciphertextData);
271 CFReleaseSafe(roundtripData);
272 }
273
274
275
276 #pragma clang diagnostic pop
277
278 #else
279
280 #endif /* TARGET_OS_MAC */
281
282
283 #endif /* kc_key_helpers_h */