keychainstasherinterface.m
1 #import <Foundation/Foundation.h> 2 #import <Foundation/NSXPCConnection_Private.h> 3 #import <Foundation/NSData_Private.h> 4 5 #include "utilities/debugging.h" 6 7 #import "KeychainStasherProtocol.h" 8 #import "keychainstasherinterface.h" 9 10 NSString* const KeychainStasherMachServiceName = @"com.apple.security.KeychainStasher"; 11 12 OSStatus stashKeyWithStashAgent(uid_t client, void const* keybytes, size_t keylen) { 13 if (!keybytes || keylen == 0) { 14 secerror("KeychainStasherInterface: No or truncated key, won't stash"); 15 return errSecParam; 16 } 17 18 secnotice("KeychainStasherInterface", "Reaching out to agent to stash key"); 19 __block OSStatus result = errSecInternalError; 20 @autoreleasepool { 21 NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:KeychainStasherMachServiceName options:0]; 22 [connection _setTargetUserIdentifier: client]; 23 connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(KeychainStasherProtocol)]; 24 [connection resume]; 25 26 id<KeychainStasherProtocol> proxy = [connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { 27 secerror("KeychainStasherInterface: errorhandler for agent called: %@", error); 28 result = errSecIO; 29 }]; 30 31 NSData* key = [NSData _newZeroingDataWithBytes:keybytes length:keylen]; 32 [proxy stashKey:key withReply:^(NSError* error) { 33 if (error) { 34 secerror("KeychainStasherInterface: agent failed to stash key: %@", error); 35 result = (int)error.code; 36 } else { 37 result = errSecSuccess; 38 } 39 }]; 40 41 [connection invalidate]; 42 } 43 44 if (result == errSecSuccess) { 45 secnotice("KeychainStasherInterface", "Successfully stashed key"); 46 } 47 return result; 48 } 49 50 OSStatus loadKeyFromStashAgent(uid_t client, void** keybytes, size_t* keylen) { 51 if (!keybytes || !keylen) { 52 secerror("KeychainStasherInterface: No outparams for key, won't load"); 53 return errSecParam; 54 } 55 56 secnotice("KeychainStasherInterface", "Reaching out to agent to retrieve key"); 57 __block OSStatus result = errSecInternalError; 58 @autoreleasepool { 59 NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:KeychainStasherMachServiceName options:0]; 60 [connection _setTargetUserIdentifier: client]; 61 connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(KeychainStasherProtocol)]; 62 [connection resume]; 63 64 id<KeychainStasherProtocol> proxy = [connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { 65 secerror("KeychainStasherInterface: errorhandler for agent called: %@", error); 66 result = errSecIO; 67 }]; 68 69 [proxy loadKeyWithReply:^(NSData *key, NSError *error) { 70 if (!key) { 71 secerror("KeychainStasherInterface: agent failed to load key: %@", error); 72 result = (int)error.code; 73 return; 74 } 75 *keybytes = calloc(1, key.length); 76 memcpy(*keybytes, key.bytes, key.length); 77 *keylen = key.length; 78 result = errSecSuccess; 79 }]; 80 81 [connection invalidate]; 82 } 83 84 if (result == errSecSuccess) { 85 secnotice("KeychainStasherInterface", "Successfully loaded key"); 86 } 87 return result; 88 }