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