2 #import "keychain/escrowrequest/Framework/SecEscrowRequest.h"
4 #import "keychain/escrowrequest/EscrowRequestXPCProtocol.h"
5 #import "keychain/escrowrequest/EscrowRequestXPCServer.h"
7 #import "utilities/debugging.h"
9 NSString* const SecEscrowRequestHavePrecord = @"have_prerecord";
10 NSString* const SecEscrowRequestPendingPasscode = @"pending_passcode";
11 NSString* const SecEscrowRequestPendingCertificate = @"pending_certificate";
13 @interface SecEscrowRequest ()
14 @property NSXPCConnection *connection;
17 @implementation SecEscrowRequest
19 + (SecEscrowRequest* _Nullable)request:(NSError* _Nullable *)error
21 NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:@(kSecuritydEscrowRequestServiceName) options:0];
23 if (connection == nil) {
25 *error = [NSError errorWithDomain:@"securityd" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Couldn't create connection (no reason given)"}];
30 NSXPCInterface *interface = SecEscrowRequestSetupControlProtocol([NSXPCInterface interfaceWithProtocol:@protocol(EscrowRequestXPCProtocol)]);
31 connection.remoteObjectInterface = interface;
34 SecEscrowRequest* c = [[SecEscrowRequest alloc] initWithConnection:connection];
38 - (instancetype)initWithConnection:(NSXPCConnection*)connection {
39 if(self = [super init]) {
40 _connection = connection;
47 [self.connection invalidate];
50 // Actual implementation
52 - (BOOL)triggerEscrowUpdate:(NSString*)reason error:(NSError**)error
54 __block NSError* localError = nil;
56 NSXPCConnection<EscrowRequestXPCProtocol>* c = [self.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *xpcError) {
57 localError = xpcError;
58 secnotice("escrow", "triggerEscrowUpdate: Failed to get XPC connection: %@", xpcError);
61 [c triggerEscrowUpdate:reason
62 reply:^(NSError * _Nullable xpcError) {
63 localError = xpcError;
65 secnotice("escrow", "Triggered escrow update for '%@': %@", reason, xpcError);
68 if(error && localError) {
72 return localError == nil;
75 - (BOOL)cachePrerecord:(NSString*)uuid
76 serializedPrerecord:(NSData*)prerecord
77 error:(NSError**)error
79 __block NSError* localError = nil;
81 NSXPCConnection<EscrowRequestXPCProtocol>* c = [self.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *xpcError) {
82 localError = xpcError;
83 secnotice("escrow", "cachePrerecord: Failed to get XPC connection: %@", xpcError);
86 [c cachePrerecord:uuid
87 serializedPrerecord:prerecord
88 reply:^(NSError * _Nullable xpcError) {
89 localError = xpcError;
91 secnotice("escrow", "Cached prerecord for %@: %@", uuid, xpcError);
94 if(error && localError) {
98 return localError == nil;
101 - (NSData* _Nullable)fetchPrerecord:(NSString*)prerecordUUID
102 error:(NSError**)error
104 __block NSError* localError = nil;
106 NSXPCConnection<EscrowRequestXPCProtocol>* c = [self.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *xpcError) {
107 localError = xpcError;
108 secnotice("escrow", "fetchprerecord: Failed to get XPC connection: %@", xpcError);
111 __block NSData* prerecord = nil;
112 [c fetchPrerecord:prerecordUUID reply:^(NSData * _Nullable requestContents, NSError * _Nullable xpcError) {
113 prerecord = requestContents;
114 localError = xpcError;
116 secnotice("escrow", "Received prerecord for %@: %@", prerecordUUID, xpcError);
119 if(error && localError) {
126 - (NSString* _Nullable)fetchRequestWaitingOnPasscode:(NSError**)error
128 __block NSError* localError = nil;
130 NSXPCConnection<EscrowRequestXPCProtocol>* c = [self.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *xpcError) {
131 localError = xpcError;
132 secnotice("escrow", "fetchRequestWaitingOnPasscode: Failed to get XPC connection: %@", xpcError);
135 __block NSString* uuid = nil;
136 [c fetchRequestWaitingOnPasscode:^(NSString * _Nullable requestUUID, NSError * _Nullable xpcError) {
138 localError = xpcError;
140 secnotice("escrow", "Received request waiting on passcode: %@ %@", requestUUID, xpcError);
143 if(error && localError) {
150 - (NSDictionary * _Nullable)fetchStatuses:(NSError**)error
152 __block NSError* localError = nil;
153 __block NSDictionary<NSString*, NSString*>* statuses = nil;
155 NSXPCConnection<EscrowRequestXPCProtocol>* c = [self.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *xpcError) {
156 localError = xpcError;
157 secnotice("escrow", "requestStatuses: Failed to get XPC connection: %@", xpcError);
160 [c fetchRequestStatuses:^(NSDictionary<NSString*,NSString*> * _Nullable fetchedStatuses, NSError * _Nullable xpcError) {
161 statuses = fetchedStatuses;
162 localError = xpcError;
164 secnotice("escrow", "Received statuses: %@ %@", statuses, xpcError);
167 if(error && localError) {
174 - (BOOL)resetAllRequests:(NSError**)error
176 __block NSError* localError = nil;
178 NSXPCConnection<EscrowRequestXPCProtocol>* c = [self.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *xpcError) {
179 localError = xpcError;
180 secnotice("escrow", "resetAllRequests: Failed to get XPC connection: %@", xpcError);
183 [c resetAllRequests:^(NSError * _Nullable xpcError) {
184 localError = xpcError;
186 secnotice("escrow", "resetAllRequests: %@", xpcError);
189 if(error && localError) {
193 return localError == nil;
196 - (uint64_t)storePrerecordsInEscrow:(NSError**)error
198 __block NSError* localError = nil;
200 NSXPCConnection<EscrowRequestXPCProtocol>* c = [self.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *xpcError) {
201 localError = xpcError;
202 secnotice("escrow", "fetchRequestWaitingOnPasscode: Failed to get XPC connection: %@", xpcError);
205 __block uint64_t count = 0;
206 [c storePrerecordsInEscrow:^(uint64_t requestCount, NSError * _Nullable xpcError) {
207 count = requestCount;
208 localError = xpcError;
210 secnotice("escrow", "Stored %d records: %@", (int)requestCount, xpcError);
213 if(error && localError) {
220 - (bool)pendingEscrowUpload:(NSError**)error
222 NSError* localError = nil;
224 NSDictionary<NSString*, NSString*>* result = [self fetchStatuses:&localError];
226 secnotice("escrow", "failed to fetch escrow statuses: %@", localError);
232 if(result == nil || (result && [result count] == 0)) {
236 BOOL inProgress = NO;
237 for(NSString* status in result.allValues) {
238 if([status isEqualToString:SecEscrowRequestHavePrecord] ||
239 [status isEqualToString:SecEscrowRequestPendingPasscode] ||
240 [status isEqualToString:SecEscrowRequestPendingCertificate]) {