1/* 2 * Copyright (c) 2011-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 "testpolicy.h" 26 27#include <TargetConditionals.h> 28 29#if TARGET_OS_IPHONE 30 31#include <Foundation/Foundation.h> 32#include <CoreFoundation/CoreFoundation.h> 33#include <utilities/SecCFWrappers.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> 40#include <stdlib.h> 41#include <unistd.h> 42 43#include "testmore.h" 44 45/* 46 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. 47 */ 48 49#include <Foundation/Foundation.h> 50#include <CoreFoundation/CoreFoundation.h> 51#include <Security/SecCertificate.h> 52#include <Security/SecCertificatePriv.h> 53#include <Security/SecInternal.h> 54#include <Security/SecPolicyPriv.h> 55#include <Security/SecTrust.h> 56#include <Security/SecTrustPriv.h> 57#include <stdlib.h> 58#include <unistd.h> 59 60#include "testmore.h" 61 62/* Those tests were originally written around that date. */ 63CFGiblisGetSingleton(CFDateRef, GetFrozenTime, frozenTime, ^{ 64 *frozenTime = CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1); 65}); 66 67static void runOneLeafTest(SecPolicyRef policy, 68 NSArray* anchors, 69 NSArray* intermediates, 70 NSString* path, 71 bool expectedResult, 72 NSObject* expectations, 73 CFDateRef date) 74{ 75 NSString* fileName = [path lastPathComponent]; 76 const char *reason = NULL; 77 SecTrustRef trustRef = NULL; 78 CFStringRef failReason = NULL; 79 NSMutableArray* certArray = NULL; 80 SecCertificateRef certRef = NULL; 81 82 if (expectations) { 83 if ([expectations isKindOfClass: [NSString class]]) { 84 reason = [(NSString *)expectations UTF8String]; 85 } else if ([expectations isKindOfClass: [NSDictionary class]]) { 86 NSDictionary *dict = (NSDictionary *)expectations; 87 NSObject *value = [dict valueForKey:@"valid"]; 88 if (value) { 89 if ([value isKindOfClass: [NSNumber class]]) { 90 expectedResult = [(NSNumber *)value boolValue]; 91 } else { 92 NSLog(@"Unexpected valid value %@ in dict for key %@", value, fileName); 93 } 94 } 95 value = [dict valueForKey:@"reason"]; 96 if (value) { 97 if ([value isKindOfClass: [NSString class]]) { 98 reason = [(NSString *)value UTF8String]; 99 } else { 100 NSLog(@"Unexpected reason value %@ in dict for key %@", value, fileName); 101 } 102 } 103 } else if ([expectations isKindOfClass: [NSNumber class]]) { 104 expectedResult = [(NSNumber *)expectations boolValue]; 105 } else { 106 NSLog(@"Unexpected class %@ value %@ for key %@", [expectations class], expectations, fileName); 107 } 108 } 109 110 certRef = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]); 111 if (!certRef) { 112 if (reason) { 113 todo(reason); 114 fail("%@ unable to create certificate", fileName); 115 } else { 116 fail("PARSE %@ unable to create certificate", fileName); 117 } 118 goto exit; 119 } 120 121 certArray = [NSMutableArray arrayWithArray:intermediates]; 122 [certArray insertObject:(id)certRef atIndex:0]; //The certificate to be verified must be the first in the array. 123 124 OSStatus err; 125 err = SecTrustCreateWithCertificates(certArray, policy, &trustRef); 126 if (err) { 127 ok_status(err, "SecTrustCreateWithCertificates"); 128 goto exit; 129 } 130 if ([anchors count]) 131 SecTrustSetAnchorCertificates(trustRef, (CFArrayRef)anchors); 132 133 SecTrustSetVerifyDate(trustRef, date ? date : GetFrozenTime()); 134 135 SecTrustResultType evalRes = 0; 136 //NSLog(@"Evaluating: %@",certRef); 137 err = SecTrustEvaluate(trustRef, &evalRes); 138 if (err) { 139 ok_status(err, "SecTrustCreateWithCertificates"); 140 goto exit; 141 } 142 BOOL isValid = (evalRes == kSecTrustResultProceed || evalRes == kSecTrustResultUnspecified); 143 if (!isValid && expectedResult) { 144 failReason = SecTrustCopyFailureDescription(trustRef); 145 } 146 if (reason) { 147 todo(reason); 148 ok(isValid == expectedResult, "%@%@", 149 fileName, 150 (expectedResult 151 ? (failReason ? failReason : CFSTR("")) 152 : CFSTR(" valid"))); 153 } else { 154 ok(isValid == expectedResult, "%s %@%@", 155 expectedResult ? "REGRESSION" : "SECURITY", fileName, 156 failReason ? failReason : CFSTR("")); 157 } 158 159exit: 160 CFReleaseSafe(failReason); 161 CFReleaseSafe(trustRef); 162 CFReleaseSafe(certRef); 163} 164 165// TODO: Export this interface in a better way. 166static void runCertificateTestFor(SecPolicyRef policy, 167 NSArray* anchors, 168 NSArray* intermediates, 169 NSMutableArray* leafPaths, 170 NSDictionary* expect, 171 CFDateRef date) 172{ 173 /* Sort the tests by name. */ 174 [leafPaths sortUsingSelector:@selector(compare:)]; 175 176 for (NSString* path in leafPaths) { 177 NSString* fileName = [path lastPathComponent]; 178 runOneLeafTest(policy, anchors, intermediates, path, ![fileName hasPrefix:@"Invalid"], [expect objectForKey:fileName], date); 179 } 180} 181 182void runCertificateTestForDirectory(SecPolicyRef policy, CFStringRef resourceSubDirectory, CFDateRef date) 183{ 184 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 185 NSMutableArray* allRoots = [NSMutableArray array]; 186 NSMutableArray* allCAs = [NSMutableArray array]; 187 NSMutableArray* certTests = [NSMutableArray array]; 188 NSDictionary* expect = NULL; 189 190 /* Iterate though the nist-certs resources dir. */ 191 NSURL* filesDirectory = [[[NSBundle mainBundle] resourceURL] URLByAppendingPathComponent:(NSString*)resourceSubDirectory]; 192 for (NSURL* fileURL in [[NSFileManager defaultManager] contentsOfDirectoryAtURL:filesDirectory includingPropertiesForKeys:[NSArray array] options:NSDirectoryEnumerationSkipsSubdirectoryDescendants error:nil]) { 193 NSString* path = [fileURL path]; 194 if ([path hasSuffix:@"Cert.crt"]) { 195 SecCertificateRef certRef = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]); 196 [allCAs addObject:(id)certRef]; 197 } else if ([path hasSuffix:@"RootCertificate.crt"]) { 198 SecCertificateRef certRef = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]); 199 [allRoots addObject:(id)certRef]; 200 } else if ([path hasSuffix:@".crt"]) { 201 [certTests addObject:path]; 202 } else if ([path hasSuffix:@".plist"]) { 203 if (expect) { 204 fail("Multiple .plist files found in %@", filesDirectory); 205 } else { 206 expect = [NSDictionary dictionaryWithContentsOfFile:path]; 207 } 208 } 209 } 210 211 runCertificateTestFor(policy, allRoots, allCAs, certTests, expect, date); 212 213 [pool release]; 214} 215 216#endif /* TARGET_OS_IPHONE */ 217