]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Regressions/secitem/si-68-secmatchissuer.c
Security-58286.1.32.tar.gz
[apple/security.git] / OSX / sec / Security / Regressions / secitem / si-68-secmatchissuer.c
1 /*
2 * Copyright (c) 2012-2017 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 "shared_regressions.h"
44 #include <test/testcert.h>
45
46 /*
47 static 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
60 static 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
74 static OSStatus add_item(CFTypeRef item)
75 {
76 CFDictionaryRef add_query = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, &item, 1, NULL, NULL);
77 OSStatus status = SecItemAdd(add_query, NULL);
78 CFRelease(add_query);
79 return status;
80 }
81
82 static OSStatus remove_item(CFTypeRef item)
83 {
84 CFDictionaryRef remove_query = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, &item, 1, NULL, NULL);
85 OSStatus status = SecItemDelete(remove_query);
86 CFRelease(remove_query);
87 return status;
88 }
89
90 static 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(2048, 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 CFReleaseNull(all_matching_identities);
175 //CFShow(all_matching_identities);
176 }
177
178 #if TARGET_OS_IPHONE
179 {
180 int limit = 0x7fff; // To regress-test <rdar://problem/14603111>
181 CFNumberRef cfLimit = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &limit);
182 const void *keys[] = { kSecClass, kSecReturnRef, kSecMatchLimit, kSecMatchIssuers };
183 const void *vals[] = { kSecClassCertificate, kCFBooleanTrue, cfLimit, all_distinguished_names };
184 CFDictionaryRef all_identities_query = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, array_size(keys), NULL, NULL);
185 CFTypeRef all_matching_certificates = NULL;
186 ok_status(SecItemCopyMatching(all_identities_query, &all_matching_certificates), "find all certificates matching");
187 CFReleaseNull(all_identities_query);
188 ok(((CFArrayGetTypeID() == CFGetTypeID(all_matching_certificates)) && (CFArrayGetCount(all_matching_certificates) == 2)), "return 2");
189 //CFShow(all_matching_certificates);
190 CFReleaseSafe(cfLimit);
191 CFReleaseNull(all_matching_certificates);
192 }
193 #else
194 /* On macOS, we don't allow kSecMatchIssuers to be used with kSecClassCertificate because performance is bad. */
195 {
196 int limit = 0x7fff; // To regress-test <rdar://problem/14603111>
197 CFNumberRef cfLimit = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &limit);
198 const void *keys[] = { kSecClass, kSecReturnRef, kSecMatchLimit, kSecMatchIssuers };
199 const void *vals[] = { kSecClassCertificate, kCFBooleanTrue, cfLimit, all_distinguished_names };
200 CFDictionaryRef all_identities_query = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, array_size(keys), NULL, NULL);
201 CFTypeRef all_matching_certificates = NULL;
202 is(errSecParam, SecItemCopyMatching(all_identities_query, &all_matching_certificates), "find all certificates matching");
203 CFReleaseNull(all_identities_query);
204 CFReleaseSafe(cfLimit);
205 CFReleaseNull(all_matching_certificates);
206 }
207 #endif
208
209 remove_item(leaf_identity);
210 CFRelease(leaf_identity);
211 CFRelease(leaf_cert);
212
213 remove_item(intermediate_cert);
214 CFRelease(intermediate_cert);
215 CFRelease(intermediate_identity);
216
217 CFRelease(ca_cert);
218 CFRelease(ca_identity);
219
220 CFRelease(public_key);
221 CFRelease(private_key);
222
223 }
224
225 int si_68_secmatchissuer(int argc, char *const *argv)
226 {
227 #if TARGET_OS_IPHONE
228 plan_tests(10);
229 #else
230 plan_tests(9);
231 #endif
232
233 tests();
234
235 return 0;
236 }