5 // Created by Mitch Adler on 7/21/11.
6 // Copyright (c) 2011 Apple Inc. All rights reserved.
9 #include "testpolicy.h"
11 #include <TargetConditionals.h>
15 #include <Foundation/Foundation.h>
16 #include <CoreFoundation/CoreFoundation.h>
17 #include <Security/SecCertificate.h>
18 #include <Security/SecCertificatePriv.h>
19 #include <Security/SecInternal.h>
20 #include <Security/SecPolicyPriv.h>
21 #include <Security/SecTrust.h>
22 #include <Security/SecTrustPriv.h>
29 * Copyright (c) 2011 Apple Inc. All Rights Reserved.
32 #include <Foundation/Foundation.h>
33 #include <CoreFoundation/CoreFoundation.h>
34 #include <Security/SecCertificate.h>
35 #include <Security/SecCertificatePriv.h>
36 #include <Security/SecInternal.h>
37 #include <Security/SecPolicyPriv.h>
38 #include <Security/SecTrust.h>
39 #include <Security/SecTrustPriv.h>
45 /* Those tests were originally written around that date. */
46 CFGregorianDate frozenTime = {
55 static void runOneLeafTest(SecPolicyRef policy,
57 NSArray* intermediates,
60 NSObject* expectations,
61 CFGregorianDate *date)
63 NSString* fileName = [path lastPathComponent];
64 const char *reason = NULL;
65 SecTrustRef trustRef = NULL;
66 CFStringRef failReason = NULL;
67 NSMutableArray* certArray = NULL;
68 SecCertificateRef certRef = NULL;
71 if ([expectations isKindOfClass: [NSString class]]) {
72 reason = [(NSString *)expectations UTF8String];
73 } else if ([expectations isKindOfClass: [NSDictionary class]]) {
74 NSDictionary *dict = (NSDictionary *)expectations;
75 NSObject *value = [dict valueForKey:@"valid"];
77 if ([value isKindOfClass: [NSNumber class]]) {
78 expectedResult = [(NSNumber *)value boolValue];
80 NSLog(@"Unexpected valid value %@ in dict for key %@", value, fileName);
83 value = [dict valueForKey:@"reason"];
85 if ([value isKindOfClass: [NSString class]]) {
86 reason = [(NSString *)value UTF8String];
88 NSLog(@"Unexpected reason value %@ in dict for key %@", value, fileName);
91 } else if ([expectations isKindOfClass: [NSNumber class]]) {
92 expectedResult = [(NSNumber *)expectations boolValue];
94 NSLog(@"Unexpected class %@ value %@ for key %@", [expectations class], expectations, fileName);
98 certRef = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]);
102 fail("%@ unable to create certificate", fileName);
104 fail("PARSE %@ unable to create certificate", fileName);
109 certArray = [NSMutableArray arrayWithArray:intermediates];
110 [certArray insertObject:(id)certRef atIndex:0]; //The certificate to be verified must be the first in the array.
113 err = SecTrustCreateWithCertificates(certArray, policy, &trustRef);
115 ok_status(err, "SecTrustCreateWithCertificates");
119 SecTrustSetAnchorCertificates(trustRef, (CFArrayRef)anchors);
121 CFDateRef dateRef = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(date?*date:frozenTime, NULL));
122 SecTrustSetVerifyDate(trustRef, dateRef);
125 SecTrustResultType evalRes = 0;
126 //NSLog(@"Evaluating: %@",certRef);
127 err = SecTrustEvaluate(trustRef, &evalRes);
129 ok_status(err, "SecTrustCreateWithCertificates");
132 BOOL isValid = (evalRes == kSecTrustResultProceed || evalRes == kSecTrustResultUnspecified);
133 if (!isValid && expectedResult) {
134 failReason = SecTrustCopyFailureDescription(trustRef);
138 ok(isValid == expectedResult, "%@%@",
141 ? (failReason ? failReason : CFSTR(""))
144 ok(isValid == expectedResult, "%s %@%@",
145 expectedResult ? "REGRESSION" : "SECURITY", fileName,
146 failReason ? failReason : CFSTR(""));
150 CFReleaseSafe(failReason);
151 CFReleaseSafe(trustRef);
152 CFReleaseSafe(certRef);
155 // TODO: Export this interface in a better way.
156 static void runCertificateTestFor(SecPolicyRef policy,
158 NSArray* intermediates,
159 NSMutableArray* leafPaths,
160 NSDictionary* expect,
161 CFGregorianDate *date)
163 /* Sort the tests by name. */
164 [leafPaths sortUsingSelector:@selector(compare:)];
166 for (NSString* path in leafPaths) {
167 NSString* fileName = [path lastPathComponent];
168 runOneLeafTest(policy, anchors, intermediates, path, ![fileName hasPrefix:@"Invalid"], [expect objectForKey:fileName], date);
172 void runCertificateTestForDirectory(SecPolicyRef policy, CFStringRef resourceSubDirectory, CFGregorianDate *date)
174 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
175 NSMutableArray* allRoots = [NSMutableArray array];
176 NSMutableArray* allCAs = [NSMutableArray array];
177 NSMutableArray* certTests = [NSMutableArray array];
178 NSDictionary* expect = NULL;
180 /* Iterate though the nist-certs resources dir. */
181 NSURL* filesDirectory = [[[NSBundle mainBundle] resourceURL] URLByAppendingPathComponent:(NSString*)resourceSubDirectory];
182 for (NSURL* fileURL in [[NSFileManager defaultManager] contentsOfDirectoryAtURL:filesDirectory includingPropertiesForKeys:[NSArray array] options:NSDirectoryEnumerationSkipsSubdirectoryDescendants error:nil]) {
183 NSString* path = [fileURL path];
184 if ([path hasSuffix:@"Cert.crt"]) {
185 SecCertificateRef certRef = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]);
186 [allCAs addObject:(id)certRef];
187 } else if ([path hasSuffix:@"RootCertificate.crt"]) {
188 SecCertificateRef certRef = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]);
189 [allRoots addObject:(id)certRef];
190 } else if ([path hasSuffix:@".crt"]) {
191 [certTests addObject:path];
192 } else if ([path hasSuffix:@".plist"]) {
194 fail("Multiple .plist files found in %@", filesDirectory);
196 expect = [NSDictionary dictionaryWithContentsOfFile:path];
201 runCertificateTestFor(policy, allRoots, allCAs, certTests, expect, date);
206 #endif /* TARGET_OS_IPHONE */