1/*
2 * Copyright (c) 2008-2010,2012-2014 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
25#include <CoreFoundation/CoreFoundation.h>
26#include <Security/SecCertificate.h>
27#include <Security/SecItem.h>
28#include <Security/SecItemPriv.h>
29#include <Security/SecBase.h>
30#include <stdlib.h>
31#include <unistd.h>
32
33#include "Security_regressions.h"
34
35#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) {  (CF) = NULL; CFRelease(_cf); } }
36
37/*
38	subject= /O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign International Server CA - Class 3/OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign
39	issuer= /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
40	serial=254B8A853842CCE358F8C5DDAE226EA4
41*/
42const uint8_t _myCert[] = {
43    0x30, 0x82, 0x03, 0x83, 0x30, 0x82, 0x02, 0xec,
44    0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x25,
45    0x4b, 0x8a, 0x85, 0x38, 0x42, 0xcc, 0xe3, 0x58,
46    0xf8, 0xc5, 0xdd, 0xae, 0x22, 0x6e, 0xa4, 0x30,
47    0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
48    0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5f,
49    0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
50    0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30,
51    0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e,
52    0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e,
53    0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x37,
54    0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
55    0x2e, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33,
56    0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
57    0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20,
58    0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
59    0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75,
60    0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30,
61    0x1e, 0x17, 0x0d, 0x39, 0x37, 0x30, 0x34, 0x31,
62    0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
63    0x17, 0x0d, 0x31, 0x31, 0x31, 0x30, 0x32, 0x34,
64    0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30,
65    0x81, 0xba, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03,
66    0x55, 0x04, 0x0a, 0x13, 0x16, 0x56, 0x65, 0x72,
67    0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72,
68    0x75, 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77,
69    0x6f, 0x72, 0x6b, 0x31, 0x17, 0x30, 0x15, 0x06,
70    0x03, 0x55, 0x04, 0x0b, 0x13, 0x0e, 0x56, 0x65,
71    0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20,
72    0x49, 0x6e, 0x63, 0x2e, 0x31, 0x33, 0x30, 0x31,
73    0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56,
74    0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20,
75    0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74,
76    0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65,
77    0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x20,
78    0x2d, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20,
79    0x33, 0x31, 0x49, 0x30, 0x47, 0x06, 0x03, 0x55,
80    0x04, 0x0b, 0x13, 0x40, 0x77, 0x77, 0x77, 0x2e,
81    0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e,
82    0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53,
83    0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x2e,
84    0x62, 0x79, 0x20, 0x52, 0x65, 0x66, 0x2e, 0x20,
85    0x4c, 0x49, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54,
86    0x59, 0x20, 0x4c, 0x54, 0x44, 0x2e, 0x28, 0x63,
87    0x29, 0x39, 0x37, 0x20, 0x56, 0x65, 0x72, 0x69,
88    0x53, 0x69, 0x67, 0x6e, 0x30, 0x81, 0x9f, 0x30,
89    0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
90    0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81,
91    0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81,
92    0x00, 0xd8, 0x82, 0x80, 0xe8, 0xd6, 0x19, 0x02,
93    0x7d, 0x1f, 0x85, 0x18, 0x39, 0x25, 0xa2, 0x65,
94    0x2b, 0xe1, 0xbf, 0xd4, 0x05, 0xd3, 0xbc, 0xe6,
95    0x36, 0x3b, 0xaa, 0xf0, 0x4c, 0x6c, 0x5b, 0xb6,
96    0xe7, 0xaa, 0x3c, 0x73, 0x45, 0x55, 0xb2, 0xf1,
97    0xbd, 0xea, 0x97, 0x42, 0xed, 0x9a, 0x34, 0x0a,
98    0x15, 0xd4, 0xa9, 0x5c, 0xf5, 0x40, 0x25, 0xdd,
99    0xd9, 0x07, 0xc1, 0x32, 0xb2, 0x75, 0x6c, 0xc4,
100    0xca, 0xbb, 0xa3, 0xfe, 0x56, 0x27, 0x71, 0x43,
101    0xaa, 0x63, 0xf5, 0x30, 0x3e, 0x93, 0x28, 0xe5,
102    0xfa, 0xf1, 0x09, 0x3b, 0xf3, 0xb7, 0x4d, 0x4e,
103    0x39, 0xf7, 0x5c, 0x49, 0x5a, 0xb8, 0xc1, 0x1d,
104    0xd3, 0xb2, 0x8a, 0xfe, 0x70, 0x30, 0x95, 0x42,
105    0xcb, 0xfe, 0x2b, 0x51, 0x8b, 0x5a, 0x3c, 0x3a,
106    0xf9, 0x22, 0x4f, 0x90, 0xb2, 0x02, 0xa7, 0x53,
107    0x9c, 0x4f, 0x34, 0xe7, 0xab, 0x04, 0xb2, 0x7b,
108    0x6f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81,
109    0xe3, 0x30, 0x81, 0xe0, 0x30, 0x0f, 0x06, 0x03,
110    0x55, 0x1d, 0x13, 0x04, 0x08, 0x30, 0x06, 0x01,
111    0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x44, 0x06,
112    0x03, 0x55, 0x1d, 0x20, 0x04, 0x3d, 0x30, 0x3b,
113    0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01,
114    0x86, 0xf8, 0x45, 0x01, 0x07, 0x01, 0x01, 0x30,
115    0x2a, 0x30, 0x28, 0x06, 0x08, 0x2b, 0x06, 0x01,
116    0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, 0x68,
117    0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77,
118    0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73,
119    0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
120    0x43, 0x50, 0x53, 0x30, 0x34, 0x06, 0x03, 0x55,
121    0x1d, 0x25, 0x04, 0x2d, 0x30, 0x2b, 0x06, 0x08,
122    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,
123    0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
124    0x03, 0x02, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
125    0x86, 0xf8, 0x42, 0x04, 0x01, 0x06, 0x0a, 0x60,
126    0x86, 0x48, 0x01, 0x86, 0xf8, 0x45, 0x01, 0x08,
127    0x01, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f,
128    0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x11,
129    0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8,
130    0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x01,
131    0x06, 0x30, 0x31, 0x06, 0x03, 0x55, 0x1d, 0x1f,
132    0x04, 0x2a, 0x30, 0x28, 0x30, 0x26, 0xa0, 0x24,
133    0xa0, 0x22, 0x86, 0x20, 0x68, 0x74, 0x74, 0x70,
134    0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x76,
135    0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e,
136    0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x63, 0x61, 0x33,
137    0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09,
138    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
139    0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x08,
140    0x01, 0xec, 0xe4, 0x68, 0x94, 0x03, 0x42, 0xf1,
141    0x73, 0xf1, 0x23, 0xa2, 0x3a, 0xde, 0xe9, 0xf1,
142    0xda, 0xc6, 0x54, 0xc4, 0x23, 0x3e, 0x86, 0xea,
143    0xcf, 0x6a, 0x3a, 0x33, 0xab, 0xea, 0x9c, 0x04,
144    0x14, 0x07, 0x36, 0x06, 0x0b, 0xf9, 0x88, 0x6f,
145    0xd5, 0x13, 0xee, 0x29, 0x2b, 0xc3, 0xe4, 0x72,
146    0x8d, 0x44, 0xed, 0xd1, 0xac, 0x20, 0x09, 0x2d,
147    0xe1, 0xf6, 0xe1, 0x19, 0x05, 0x38, 0xb0, 0x3d,
148    0x0f, 0x9f, 0x7f, 0xf8, 0x9e, 0x02, 0xdc, 0x86,
149    0x02, 0x86, 0x61, 0x4e, 0x26, 0x5f, 0x5e, 0x9f,
150    0x92, 0x1e, 0x0c, 0x24, 0xa4, 0xf5, 0xd0, 0x70,
151    0x13, 0xcf, 0x26, 0xc3, 0x43, 0x3d, 0x49, 0x1d,
152    0x9e, 0x82, 0x2e, 0x52, 0x5f, 0xbc, 0x3e, 0xc6,
153    0x66, 0x29, 0x01, 0x8e, 0x4e, 0x92, 0x2c, 0xbc,
154    0x46, 0x75, 0x03, 0x82, 0xac, 0x73, 0xe9, 0xd9,
155    0x7e, 0x0b, 0x67, 0xef, 0x54, 0x52, 0x1a
156};
157
158static void persistentRefIs(CFDataRef pref, CFDataRef data) {
159    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
160    CFTypeRef result = NULL;
161    CFDictionaryAddValue(dict, kSecValuePersistentRef, pref);
162    CFDictionaryAddValue(dict, kSecReturnData, kCFBooleanTrue);
163    ok_status(SecItemCopyMatching(dict, &result), "lookup item data by persistent ref");
164    ok(CFEqual(data, result), "result %@ equals expected data %@", result, data);
165    CFReleaseNull(result);
166    CFReleaseNull(dict);
167}
168
169/* Test add api in all it's variants. */
170static void tests(void)
171{
172    CFDataRef myCertData = NULL;
173	SecCertificateRef myCert = NULL;
174	CFTypeRef  certHandle = NULL;
175
176    /* Create myCert and setup dict. */
177    myCertData = CFDataCreateWithBytesNoCopy(NULL, _myCert, sizeof(_myCert),
178        kCFAllocatorNull);
179	isnt(myCert = SecCertificateCreateWithData(NULL, myCertData),
180		NULL, "create myCert");
181    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
182    CFDictionaryAddValue(dict, kSecClass, kSecClassCertificate);
183    CFDictionaryAddValue(dict, kSecValueRef, myCert);
184
185    /* Case 1: add certificate with no return pointer. */
186    ok_status(SecItemAdd(dict, NULL),
187        "Case 1: add certificate NULL return pointer");
188    ok_status(SecItemDelete(dict), "delete certificate");
189    /* Case 1b: add certificate ref should be returned implicitly. */
190    ok_status(SecItemAdd(dict, &certHandle),
191              "Case 1: add certificate dont ask for return type");
192    // See also: "<rdar://problem/7091317493> SecItemAdd unimplemented feature";
193    is(certHandle, NULL, "nothing returned");
194    CFReleaseNull(certHandle);
195    ok_status(SecItemDelete(dict), "delete certificate");
196
197    /* Case 2: add certificate ask for persistent ref. */
198    CFDictionaryAddValue(dict, kSecReturnPersistentRef, kCFBooleanTrue);
199    ok_status(SecItemAdd(dict, &certHandle),
200        "Case 2: add certificate ask for persistent ref");
201    is(CFGetTypeID(certHandle), CFDataGetTypeID(), "persistent ref returned");
202    /* Check if persistent ref yields cert data again when searched. */
203    persistentRefIs(certHandle, myCertData);
204    CFReleaseNull(certHandle);
205    CFDictionaryRemoveValue(dict, kSecReturnPersistentRef);
206    ok_status(SecItemDelete(dict), "delete certificate");
207
208    /* Case 3: add certificate ask for ref to be returned explicitly. */
209    CFDictionaryAddValue(dict, kSecReturnRef, kCFBooleanTrue);
210    ok_status(SecItemAdd(dict, &certHandle),
211        "Case 3: add certificate ask for ref to be returned explicitly");
212    ok(CFEqual(myCert, certHandle), "certificate ref matches");
213    CFReleaseNull(certHandle);
214    CFDictionaryRemoveValue(dict, kSecReturnRef);
215    ok_status(SecItemDelete(dict), "delete certificate");
216
217    /* Case 4: add certificate ask for data to be returned explicitly. */
218    CFDictionaryAddValue(dict, kSecReturnData, kCFBooleanTrue);
219    ok_status(SecItemAdd(dict, &certHandle),
220        "Case 4: add certificate ask for data to be returned explicitly");
221    ok(CFEqual(myCertData, certHandle), "certificate data matches");
222    CFReleaseNull(certHandle);
223    CFDictionaryRemoveValue(dict, kSecReturnData);
224    ok_status(SecItemDelete(dict), "delete certificate");
225
226    /* Case 5: add certificate ask for attributes to be returned explicitly. */
227    CFDictionaryAddValue(dict, kSecReturnAttributes, kCFBooleanTrue);
228    ok_status(SecItemAdd(dict, &certHandle),
229        "Case 5: add certificate ask for attributes to be returned explicitly");
230    is(CFGetTypeID(certHandle), CFDictionaryGetTypeID(), "result is a dict");
231    ok(!CFDictionaryContainsKey(certHandle, kSecValueData),
232        "result has no data");
233    ok(!CFDictionaryContainsKey(certHandle, kSecValueRef),
234        "result has no ref");
235    ok(!CFDictionaryContainsKey(certHandle, kSecValuePersistentRef),
236        "result has no persistent ref");
237    /* @@@ Check attribute values. Against this list:
238        kSecClassCertificate item attributes:
239        kSecAttrAccessGroup
240        kSecAttrCertificateType
241        kSecAttrCertificateEncoding
242        kSecAttrLabel
243        kSecAttrSubject
244        kSecAttrIssuer
245        kSecAttrSerialNumber
246        kSecAttrSubjectKeyID
247        kSecAttrPublicKeyHash
248    */
249    is(CFGetTypeID(CFDictionaryGetValue(certHandle, kSecAttrCertificateType)),
250        CFNumberGetTypeID(), "certificate type is a number");
251    is(CFGetTypeID(CFDictionaryGetValue(certHandle, kSecAttrCertificateEncoding)),
252        CFNumberGetTypeID(), "certificate encoding is a number");
253    CFReleaseNull(certHandle);
254    CFDictionaryRemoveValue(dict, kSecReturnAttributes);
255    ok_status(SecItemDelete(dict), "delete certificate");
256
257    /* Case 6: add certificate ask for attributes, data, ref and persistent ref
258       to be returned explicitly. */
259    CFDictionaryAddValue(dict, kSecReturnData, kCFBooleanTrue);
260    CFDictionaryAddValue(dict, kSecReturnAttributes, kCFBooleanTrue);
261    CFDictionaryAddValue(dict, kSecReturnRef, kCFBooleanTrue);
262    CFDictionaryAddValue(dict, kSecReturnPersistentRef, kCFBooleanTrue);
263    ok_status(SecItemAdd(dict, &certHandle),
264        "Case 6: add certificate ask for attributes, data, ref and persistent ref to be returned explicitly");
265    isnt(certHandle, NULL, "certificate handle returned");
266    is(CFGetTypeID(certHandle), CFDictionaryGetTypeID(), "result is a dict");
267    ok(CFEqual(myCertData, CFDictionaryGetValue(certHandle, kSecValueData)),
268        "certificate data in dict matches");
269    ok(CFEqual(myCert, CFDictionaryGetValue(certHandle, kSecValueRef)),
270        "certificate ref in dict matches");
271    /* Check if persistent ref yields cert data again when searched. */
272    persistentRefIs(CFDictionaryGetValue(certHandle, kSecValuePersistentRef),
273        myCertData);
274    ok(CFEqual(kSecClassCertificate,
275        CFDictionaryGetValue(certHandle, kSecClass)),
276        "certificate class in dict matches");
277    is(CFGetTypeID(CFDictionaryGetValue(certHandle, kSecAttrCertificateType)),
278        CFNumberGetTypeID(), "certificate type is a number");
279    is(CFGetTypeID(CFDictionaryGetValue(certHandle, kSecAttrCertificateEncoding)),
280        CFNumberGetTypeID(), "certificate encoding is a number");
281    CFReleaseNull(certHandle);
282    CFDictionaryRemoveValue(dict, kSecReturnData);
283    CFDictionaryRemoveValue(dict, kSecReturnAttributes);
284    CFDictionaryRemoveValue(dict, kSecReturnRef);
285    CFDictionaryRemoveValue(dict, kSecReturnPersistentRef);
286    ok_status(SecItemDelete(dict), "delete certificate");
287
288    /* Case 7: add certificate with bogus attribute. */
289    CFDataRef tagData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
290        (const UInt8 *)"funnytag", 8, kCFAllocatorNull);
291    CFDictionaryAddValue(dict, kSecAttrApplicationTag, tagData);
292    is_status(SecItemAdd(dict, &certHandle), errSecParam,
293        "Case 7: add certificate with bogus attribute returns errSecParam");
294    CFReleaseNull(certHandle);
295    is_status(SecItemDelete(dict), errSecParam,
296        "delete certificate with bogus attribute returns errSecParam");
297    CFDictionaryRemoveValue(dict, kSecAttrApplicationTag);
298    CFReleaseNull(tagData);
299
300    /* Case 8: add certificate with synchronizable attribute. */
301    CFDictionaryAddValue(dict, kSecAttrSynchronizable, kCFBooleanTrue);
302    ok_status(SecItemAdd(dict, &certHandle),
303              "Case 7: add certificate with synchronizable attribute works");
304    CFReleaseNull(certHandle);
305    ok_status(SecItemDelete(dict),
306              "delete certificate with synchronizable attribute works");
307    CFDictionaryRemoveValue(dict, kSecAttrSynchronizable);
308
309    /* Cleanup. */
310    CFReleaseNull(dict);
311    CFReleaseNull(myCert);
312    CFReleaseNull(myCertData);
313
314}
315
316int si_05_add(int argc, char *const *argv)
317{
318	plan_tests(40);
319
320	tests();
321
322	return 0;
323}
324