/ securityd / src / keychainstasherinterface.m
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  }