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