1 #import <Foundation/Foundation.h>
2 #import <Foundation/NSXPCConnection_Private.h>
3 #import <Foundation/NSData_Private.h>
5 #include "utilities/debugging.h"
7 #import "KeychainStasherProtocol.h"
8 #import "keychainstasherinterface.h"
10 NSString* const KeychainStasherMachServiceName = @"com.apple.security.KeychainStasher";
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");
18 secnotice("KeychainStasherInterface", "Reaching out to agent to stash key");
19 __block OSStatus result = errSecInternalError;
21 NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:KeychainStasherMachServiceName options:0];
22 [connection _setTargetUserIdentifier: client];
23 connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(KeychainStasherProtocol)];
26 id<KeychainStasherProtocol> proxy = [connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) {
27 secerror("KeychainStasherInterface: errorhandler for agent called: %@", error);
31 NSData* key = [NSData _newZeroingDataWithBytes:keybytes length:keylen];
32 [proxy stashKey:key withReply:^(NSError* error) {
34 secerror("KeychainStasherInterface: agent failed to stash key: %@", error);
35 result = (int)error.code;
37 result = errSecSuccess;
41 [connection invalidate];
44 if (result == errSecSuccess) {
45 secnotice("KeychainStasherInterface", "Successfully stashed key");
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");
56 secnotice("KeychainStasherInterface", "Reaching out to agent to retrieve key");
57 __block OSStatus result = errSecInternalError;
59 NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:KeychainStasherMachServiceName options:0];
60 [connection _setTargetUserIdentifier: client];
61 connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(KeychainStasherProtocol)];
64 id<KeychainStasherProtocol> proxy = [connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) {
65 secerror("KeychainStasherInterface: errorhandler for agent called: %@", error);
69 [proxy loadKeyWithReply:^(NSData *key, NSError *error) {
71 secerror("KeychainStasherInterface: agent failed to load key: %@", error);
72 result = (int)error.code;
75 *keybytes = calloc(1, key.length);
76 memcpy(*keybytes, key.bytes, key.length);
78 result = errSecSuccess;
81 [connection invalidate];
84 if (result == errSecSuccess) {
85 secnotice("KeychainStasherInterface", "Successfully loaded key");