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