]> git.saurik.com Git - apple/security.git/blob - tests/TrustTests/DaemonTests/OCSPCacheTests.m
Security-59754.80.3.tar.gz
[apple/security.git] / tests / TrustTests / DaemonTests / OCSPCacheTests.m
1 //
2 // OCSPCacheUpgradeTests.m
3 // Security
4 //
5 //
6
7 #include <AssertMacros.h>
8 #import <XCTest/XCTest.h>
9 #import <Security/SecCertificatePriv.h>
10 #include <utilities/SecCFWrappers.h>
11 #include <sqlite3.h>
12 #import "trust/trustd/SecOCSPRequest.h"
13 #import "trust/trustd/SecOCSPResponse.h"
14 #import "trust/trustd/SecOCSPCache.h"
15
16 #import "TrustDaemonTestCase.h"
17 #import "OCSPCacheTests_data.h"
18
19 @interface OCSPCacheTests : TrustDaemonTestCase
20 @end
21
22 @implementation OCSPCacheTests
23
24 - (void)setUp
25 {
26 /* Delete the OCSP cache DB so we can start fresh */
27 SecOCSPCacheDeleteCache();
28 }
29
30 - (BOOL)canReadDB
31 {
32 SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _leaf_cert, sizeof(_leaf_cert));
33 SecCertificateRef issuer = SecCertificateCreateWithBytes(NULL, _issuer, sizeof(_issuer));
34 SecOCSPRequestRef request = SecOCSPRequestCreate(leaf, issuer);
35 SecOCSPResponseRef response = SecOCSPCacheCopyMatching(request, NULL);
36 CFReleaseNull(leaf);
37 CFReleaseNull(issuer);
38 SecOCSPRequestFinalize(request);
39
40 if (response) {
41 SecOCSPResponseFinalize(response);
42 return YES;
43 }
44 return NO;
45 }
46
47 - (void)writeResponse1ToDB
48 {
49 NSData *responseData = [NSData dataWithBytes:_ocsp_response1 length:sizeof(_ocsp_response1)];
50 SecOCSPResponseRef response = SecOCSPResponseCreate((__bridge CFDataRef)responseData);
51 /* use a verifyTime within the validity of the ocsp response */
52 (void)SecOCSPResponseCalculateValidity(response, 0, 60, 595602000.0); // as a side effect, populates the expire time
53 SecOCSPCacheReplaceResponse(NULL, response, NULL, 595602000.0);
54 SecOCSPResponseFinalize(response);
55 }
56
57 - (void)writeResponse2ToDB
58 {
59 NSData *responseData = [NSData dataWithBytes:_ocsp_response2 length:sizeof(_ocsp_response2)];
60 SecOCSPResponseRef response = SecOCSPResponseCreate((__bridge CFDataRef)responseData);
61 (void)SecOCSPResponseCalculateValidity(response, 0, 60, 596180000.0); // as a side effect, populates the expire time
62 SecOCSPCacheReplaceResponse(NULL, response, NULL,596180000.0);
63 SecOCSPResponseFinalize(response);
64 }
65
66 - (void)replaceResponse
67 {
68 NSData *responseData = [NSData dataWithBytes:_ocsp_response1 length:sizeof(_ocsp_response1)];
69 SecOCSPResponseRef response1 = SecOCSPResponseCreate((__bridge CFDataRef)responseData);
70 (void)SecOCSPResponseCalculateValidity(response1, 0, 60, 595602000.0); // populate the expire time
71
72 responseData = [NSData dataWithBytes:_ocsp_response2 length:sizeof(_ocsp_response2)];
73 SecOCSPResponseRef response2 = SecOCSPResponseCreate((__bridge CFDataRef)responseData);
74 (void)SecOCSPResponseCalculateValidity(response2, 0, 60, 596180000.0); // populate the expire time
75
76 SecOCSPCacheReplaceResponse(response1, response2, NULL, 596180000.0);
77 SecOCSPResponseFinalize(response1);
78 SecOCSPResponseFinalize(response2);
79 }
80
81 - (void)createDBFromSQL:(NSString *)sql
82 {
83 CFStringRef cf_path = SecOCSPCacheCopyPath();
84 CFStringPerformWithCString(cf_path, ^(const char *path) {
85 /* Create ocsp cahche */
86 sqlite3 *db;
87 XCTAssertEqual(sqlite3_open(path, &db), SQLITE_OK, "create ocsp cache");
88 XCTAssertEqual(sqlite3_exec(db, [sql cStringUsingEncoding:NSUTF8StringEncoding], NULL, NULL, NULL), SQLITE_OK,
89 "populate ocsp cache");
90 XCTAssertEqual(sqlite3_close_v2(db), SQLITE_OK);
91
92 });
93 CFReleaseNull(cf_path);
94 }
95
96 - (int)countEntries
97 {
98 CFStringRef cf_path = SecOCSPCacheCopyPath();
99 __block int result = 0;
100 CFStringPerformWithCString(cf_path, ^(const char *path) {
101 sqlite3 *db = NULL;
102 sqlite3_stmt *stmt = NULL;
103 XCTAssertEqual(sqlite3_open(path, &db), SQLITE_OK);
104 NSString *countResponses = @"SELECT COUNT(responseId) FROM responses;";
105 XCTAssertEqual(sqlite3_prepare_v2(db, [countResponses cStringUsingEncoding:NSUTF8StringEncoding],
106 (int)[countResponses length], &stmt, NULL),
107 SQLITE_OK);
108 XCTAssertEqual(sqlite3_step(stmt), SQLITE_ROW);
109 result = sqlite3_column_int(stmt, 0);
110 XCTAssertEqual(sqlite3_finalize(stmt), SQLITE_OK);
111 XCTAssertEqual(sqlite3_close_v2(db), SQLITE_OK);
112 });
113 CFReleaseNull(cf_path);
114 return result;
115 }
116
117 - (void)testNewDatabase
118 {
119 [self writeResponse1ToDB];
120 XCTAssert([self canReadDB]);
121 }
122
123 - (void)testNewDatabaseReOpen
124 {
125 [self writeResponse1ToDB];
126 XCTAssert([self canReadDB]);
127 SecOCSPCacheCloseDB();
128 XCTAssert([self canReadDB]);
129 [self replaceResponse];
130 XCTAssert([self canReadDB]);
131 }
132
133 - (void)testOldDatabaseUpgradeNoContent
134 {
135 [self createDBFromSQL:_oldDBSchema];
136 [self writeResponse1ToDB];
137 XCTAssert([self canReadDB]);
138 }
139
140 - (void)testOldDatabaseUpgradeWithContent
141 {
142 [self createDBFromSQL:_oldDBSchemaWithContent];
143 XCTAssert([self canReadDB]);
144 [self replaceResponse];
145 XCTAssert([self canReadDB]);
146 }
147
148 - (void)testUpgradedDatabaseNoContent
149 {
150 [self createDBFromSQL:_oldDBSchema];
151 XCTAssertFalse([self canReadDB]); // should upgrade the DB
152 SecOCSPCacheCloseDB();
153 [self writeResponse1ToDB];
154 XCTAssert([self canReadDB]);
155 }
156
157 - (void)testUpgradedDatabaseWithContent
158 {
159 [self createDBFromSQL:_oldDBSchemaWithContent];
160 XCTAssert([self canReadDB]); // should upgrade the DB
161 SecOCSPCacheCloseDB();
162 [self replaceResponse];
163 XCTAssert([self canReadDB]);
164 }
165
166 - (void)testGCExpiredResponses
167 {
168 [self createDBFromSQL:_oldDBSchemaWithContent]; // since this is an old schema, the certStatus will be CS_NotParsed
169 /* don't replace response 1, just add response 2 a week after response 1 expired */
170 [self writeResponse2ToDB]; // as a side effect, should GC the expired non-revoked response
171 SecOCSPCacheCloseDB();
172 XCTAssertEqual([self countEntries], 1);
173 }
174
175 - (void)testNoGCExpiredRevokedResponses
176 {
177 [self writeResponse1ToDB];
178 /* don't replace response 1, just add response 2 a week after response 1 expired */
179 [self writeResponse2ToDB]; // should not GC the expired revoked response 1
180 SecOCSPCacheCloseDB();
181 XCTAssertEqual([self countEntries], 2);
182 }
183
184 @end