1/* 2 * Copyright (c) 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// 26// si-68-secmatchissuer.c 27// regressions 28// 29// 30// 31#include <CoreFoundation/CoreFoundation.h> 32#include <Security/Security.h> 33#include <libDER/libDER.h> 34#include <libDER/DER_Decode.h> 35#include <libDER/asn1Types.h> 36#include <Security/SecCertificateInternal.h> 37#include <Security/SecCertificatePriv.h> 38#include <Security/SecIdentityPriv.h> 39#include <Security/SecItem.h> 40#include <Security/SecInternal.h> 41#include <utilities/array_size.h> 42 43#include "Security_regressions.h" 44#include <test/testcert.h> 45 46/* 47static OSStatus add_item_to_keychain(CFTypeRef item, CFDataRef * persistent_ref) 48{ 49 const void *keys[] = { kSecValueRef, kSecReturnPersistentRef }; 50 const void *vals[] = { item, kCFBooleanTrue }; 51 CFDictionaryRef add_query = CFDictionaryCreate(NULL, keys, vals, array_size(keys), NULL, NULL); 52 OSStatus status = errSecAllocate; 53 if (add_query) { 54 status = SecItemAdd(add_query, (CFTypeRef *)persistent_ref); 55 CFRelease(add_query); 56 } 57 return status; 58} 59 60static OSStatus remove_item_from_keychain(CFTypeRef item, CFDataRef * persistent_ref) 61{ 62 const void *keys[] = { kSecValueRef, kSecReturnPersistentRef }; 63 const void *vals[] = { item, kCFBooleanTrue }; 64 CFDictionaryRef add_query = CFDictionaryCreate(NULL, keys, vals, array_size(keys), NULL, NULL); 65 OSStatus status = errSecAllocate; 66 if (add_query) { 67 status = SecItemAdd(add_query, (CFTypeRef *)persistent_ref); 68 CFRelease(add_query); 69 } 70 return status; 71} 72*/ 73 74static OSStatus add_item(CFTypeRef item) 75{ 76 CFDictionaryRef add_query = CFDictionaryCreate(NULL, &kSecValueRef, &item, 1, NULL, NULL); 77 OSStatus status = SecItemAdd(add_query, NULL); 78 CFRelease(add_query); 79 return status; 80} 81 82static OSStatus remove_item(CFTypeRef item) 83{ 84 CFDictionaryRef remove_query = CFDictionaryCreate(NULL, &kSecValueRef, &item, 1, NULL, NULL); 85 OSStatus status = SecItemDelete(remove_query); 86 CFRelease(remove_query); 87 return status; 88} 89 90static void tests(void) 91{ 92 93// MARK: test SecDistinguishedNameCopyNormalizedContent 94 95 unsigned char example_dn[] = { 96 0x30, 0x4f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 97 0x02, 0x43, 0x5a, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0a, 98 0x0c, 0x1e, 0x4d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x65, 0x72, 0x73, 0x74, 99 0x76, 0x6f, 0x20, 0x73, 0x70, 0x72, 0x61, 0x76, 0x65, 0x64, 0x6c, 0x6e, 100 0x6f, 0x73, 0x74, 0x69, 0x20, 0xc4, 0x8c, 0x52, 0x31, 0x17, 0x30, 0x15, 101 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0e, 0x4d, 0x53, 0x70, 0x20, 0x52, 102 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x30, 0x31 103 }; 104 unsigned int example_dn_len = 81; 105 106 CFDataRef normalized_dn = NULL, dn = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, example_dn, example_dn_len, kCFAllocatorNull); 107 ok(dn, "got dn as data"); 108 ok(normalized_dn = SecDistinguishedNameCopyNormalizedContent(dn), "convert to normalized form"); 109 //CFShow(dn); 110 //CFShow(normalized_dn); 111 CFReleaseNull(dn); 112 CFReleaseNull(normalized_dn); 113 114// MARK: generate certificate hierarchy 115 116 SecKeyRef public_key = NULL, private_key = NULL; 117 ok_status(test_cert_generate_key(512, kSecAttrKeyTypeRSA, &private_key, &public_key), "generate keypair"); 118 // make organization random uuid to avoid previous run to spoil the fun 119 120 CFUUIDRef UUID = CFUUIDCreate(kCFAllocatorDefault); 121 CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, UUID); 122 CFStringRef root_authority_name = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("O=%@,CN=Root CA"), uuidString); 123 CFStringRef intermediate_authority_name = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("O=%@,CN=Intermediate CA"), uuidString); 124 CFStringRef leaf_name = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("O=%@,CN=Client"), uuidString); 125 CFRelease(uuidString); 126 CFRelease(UUID); 127 128 SecIdentityRef ca_identity = 129 test_cert_create_root_certificate(root_authority_name, public_key, private_key); 130 CFRelease(root_authority_name); 131 132 SecCertificateRef ca_cert = NULL; 133 SecIdentityCopyCertificate(ca_identity, &ca_cert); 134 //CFShow(ca_cert); 135 136 SecCertificateRef intermediate_cert = 137 test_cert_issue_certificate(ca_identity, public_key, intermediate_authority_name, 42, kSecKeyUsageKeyCertSign); 138 CFRelease(intermediate_authority_name); 139 SecIdentityRef intermediate_identity = SecIdentityCreate(kCFAllocatorDefault, intermediate_cert, private_key); 140 141 ok_status(add_item(intermediate_cert), "add intermediate"); 142 //CFShow(intermediate_cert); 143 144 SecCertificateRef leaf_cert = test_cert_issue_certificate(intermediate_identity, public_key, 145 leaf_name, 4242, kSecKeyUsageDigitalSignature); 146 CFRelease(leaf_name); 147 SecIdentityRef leaf_identity = SecIdentityCreate(kCFAllocatorDefault, leaf_cert, private_key); 148 149 ok_status(add_item(leaf_identity), "add leaf"); 150 //CFShow(leaf_cert); 151 152 // this is already canonical - see if we can get the raw one 153 CFDataRef issuer = SecCertificateGetNormalizedIssuerContent(intermediate_cert); 154 ok(CFDataGetLength(issuer) < 128, "max 127 bytes of content - or else you'll need to properly encode issuer sequence"); 155 CFMutableDataRef canonical_issuer = CFDataCreateMutable(kCFAllocatorDefault, CFDataGetLength(issuer) + 2); 156 CFDataSetLength(canonical_issuer, CFDataGetLength(issuer) + 2); 157 uint8_t * ptr = CFDataGetMutableBytePtr(canonical_issuer); 158 memcpy(ptr+2, CFDataGetBytePtr(issuer), CFDataGetLength(issuer)); 159 ptr[0] = 0x30; 160 ptr[1] = CFDataGetLength(issuer); 161 162 CFMutableArrayRef all_distinguished_names = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 163 CFArrayAppendValue(all_distinguished_names, canonical_issuer); 164 165 { 166 CFReleaseNull(canonical_issuer); 167 const void *keys[] = { kSecClass, kSecReturnRef, kSecMatchLimit, kSecMatchIssuers }; 168 const void *vals[] = { kSecClassIdentity, kCFBooleanTrue, kSecMatchLimitAll, all_distinguished_names }; 169 CFDictionaryRef all_identities_query = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, array_size(keys), NULL, NULL); 170 CFTypeRef all_matching_identities = NULL; 171 ok_status(SecItemCopyMatching(all_identities_query, &all_matching_identities), "find all identities matching"); 172 CFReleaseNull(all_identities_query); 173 ok(((CFArrayGetTypeID() == CFGetTypeID(all_matching_identities)) && (CFArrayGetCount(all_matching_identities) == 2)), "return 2"); 174 //CFShow(all_matching_identities); 175 } 176 177 { 178 int limit = 0x7fff; // To regress-test <rdar://problem/14603111> 179 CFNumberRef cfLimit = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &limit); 180 const void *keys[] = { kSecClass, kSecReturnRef, kSecMatchLimit, kSecMatchIssuers }; 181 const void *vals[] = { kSecClassCertificate, kCFBooleanTrue, cfLimit, all_distinguished_names }; 182 CFDictionaryRef all_identities_query = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, array_size(keys), NULL, NULL); 183 CFTypeRef all_matching_certificates = NULL; 184 ok_status(SecItemCopyMatching(all_identities_query, &all_matching_certificates), "find all certificates matching"); 185 CFReleaseNull(all_identities_query); 186 ok(((CFArrayGetTypeID() == CFGetTypeID(all_matching_certificates)) && (CFArrayGetCount(all_matching_certificates) == 2)), "return 2"); 187 //CFShow(all_matching_certificates); 188 CFReleaseSafe(cfLimit); 189 } 190 191 remove_item(leaf_identity); 192 CFRelease(leaf_identity); 193 CFRelease(leaf_cert); 194 195 remove_item(intermediate_cert); 196 CFRelease(intermediate_cert); 197 CFRelease(intermediate_identity); 198 199 CFRelease(ca_cert); 200 CFRelease(ca_identity); 201 202 CFRelease(public_key); 203 CFRelease(private_key); 204 205} 206 207int si_68_secmatchissuer(int argc, char *const *argv) 208{ 209 plan_tests(10); 210 211 tests(); 212 213 return 0; 214} 215