2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #include "testpolicy.h"
27 #include <TargetConditionals.h>
29 #include <Foundation/Foundation.h>
30 #include <CoreFoundation/CoreFoundation.h>
31 #include <utilities/SecCFWrappers.h>
32 #include <Security/SecCertificate.h>
33 #include <Security/SecCertificatePriv.h>
34 #include <Security/SecPolicyPriv.h>
35 #include <Security/SecTrust.h>
36 #include <Security/SecTrustPriv.h>
43 /* Those tests were originally written around that date. */
44 CFGiblisGetSingleton(CFDateRef, GetFrozenTime, frozenTime, ^{
45 *frozenTime = CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1);
48 static void runOneLeafTest(SecPolicyRef policy,
50 NSArray* intermediates,
53 NSObject* expectations,
56 NSString* fileName = [path lastPathComponent];
57 const char *reason = NULL;
58 SecTrustRef trustRef = NULL;
59 CFStringRef failReason = NULL;
60 NSMutableArray* certArray = NULL;
61 SecCertificateRef certRef = NULL;
64 if ([expectations isKindOfClass: [NSString class]]) {
65 reason = [(NSString *)expectations UTF8String];
66 } else if ([expectations isKindOfClass: [NSDictionary class]]) {
67 NSDictionary *dict = (NSDictionary *)expectations;
68 NSObject *value = [dict valueForKey:@"valid"];
70 if ([value isKindOfClass: [NSNumber class]]) {
71 expectedResult = [(NSNumber *)value boolValue];
73 NSLog(@"Unexpected valid value %@ in dict for key %@", value, fileName);
76 value = [dict valueForKey:@"reason"];
78 if ([value isKindOfClass: [NSString class]]) {
79 reason = [(NSString *)value UTF8String];
81 NSLog(@"Unexpected reason value %@ in dict for key %@", value, fileName);
84 } else if ([expectations isKindOfClass: [NSNumber class]]) {
85 expectedResult = [(NSNumber *)expectations boolValue];
87 NSLog(@"Unexpected class %@ value %@ for key %@", [expectations class], expectations, fileName);
91 certRef = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]);
95 fail("%@ unable to create certificate", fileName);
97 fail("PARSE %@ unable to create certificate", fileName);
102 certArray = [NSMutableArray arrayWithArray:intermediates];
103 [certArray insertObject:(__bridge id)certRef atIndex:0]; //The certificate to be verified must be the first in the array.
106 err = SecTrustCreateWithCertificates((__bridge CFTypeRef _Nonnull)(certArray), policy, &trustRef);
108 ok_status(err, "SecTrustCreateWithCertificates");
112 SecTrustSetAnchorCertificates(trustRef, (CFArrayRef)anchors);
114 SecTrustSetVerifyDate(trustRef, date ? date : GetFrozenTime());
116 SecTrustResultType evalRes = 0;
117 //NSLog(@"Evaluating: %@",certRef);
118 err = SecTrustEvaluate(trustRef, &evalRes);
120 ok_status(err, "SecTrustEvaluate");
123 BOOL isValid = (evalRes == kSecTrustResultProceed || evalRes == kSecTrustResultUnspecified);
124 if (!isValid && expectedResult) {
125 failReason = SecTrustCopyFailureDescription(trustRef);
129 ok(isValid == expectedResult, "%@%@",
132 ? (failReason ? failReason : CFSTR(""))
135 ok(isValid == expectedResult, "%s %@%@",
136 expectedResult ? "REGRESSION" : "SECURITY", fileName,
137 failReason ? failReason : CFSTR(""));
141 CFReleaseSafe(failReason);
142 CFReleaseSafe(trustRef);
143 CFReleaseSafe(certRef);
146 // TODO: Export this interface in a better way.
147 static void runCertificateTestFor(SecPolicyRef policy,
149 NSArray* intermediates,
150 NSMutableArray* leafPaths,
151 NSDictionary* expect,
154 /* Sort the tests by name. */
155 [leafPaths sortUsingSelector:@selector(compare:)];
157 for (NSString* path in leafPaths) {
158 NSString* fileName = [path lastPathComponent];
159 runOneLeafTest(policy, anchors, intermediates, path, ![fileName hasPrefix:@"Invalid"], [expect objectForKey:fileName], date);
163 void runCertificateTestForDirectory(SecPolicyRef policy, CFStringRef resourceSubDirectory, CFDateRef date)
165 NSMutableArray* allRoots = [NSMutableArray array];
166 NSMutableArray* allCAs = [NSMutableArray array];
167 NSMutableArray* certTests = [NSMutableArray array];
168 NSDictionary* expect = NULL;
170 /* Iterate though the nist-certs resources dir. */
171 NSURL* filesDirectory = [[[NSBundle mainBundle] resourceURL] URLByAppendingPathComponent:(__bridge NSString*)resourceSubDirectory];
172 for (NSURL* fileURL in [[NSFileManager defaultManager] contentsOfDirectoryAtURL:filesDirectory includingPropertiesForKeys:[NSArray array] options:NSDirectoryEnumerationSkipsSubdirectoryDescendants error:nil]) {
173 NSString* path = [fileURL path];
174 if ([path hasSuffix:@"Cert.crt"]) {
175 SecCertificateRef certRef = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]);
176 [allCAs addObject:(__bridge id)certRef];
177 CFReleaseNull(certRef);
178 } else if ([path hasSuffix:@"RootCertificate.crt"]) {
179 SecCertificateRef certRef = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]);
180 [allRoots addObject:(__bridge id)certRef];
181 CFReleaseNull(certRef);
182 } else if ([path hasSuffix:@".crt"]) {
183 [certTests addObject:path];
184 } else if ([path hasSuffix:@".plist"]) {
186 fail("Multiple .plist files found in %@", filesDirectory);
188 expect = [NSDictionary dictionaryWithContentsOfFile:path];
193 runCertificateTestFor(policy, allRoots, allCAs, certTests, expect, date);