1 /* Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. */
3 #include "securityd_service.h"
4 #include "securityd_service_client.h"
6 #include <dispatch/dispatch.h>
8 #include <AssertMacros.h>
10 static xpc_connection_t
11 _service_get_connection()
13 static dispatch_once_t onceToken
;
14 static xpc_connection_t connection
= NULL
;
16 dispatch_once(&onceToken
, ^{
17 connection
= xpc_connection_create_mach_service(SECURITYD_SERVICE_NAME
, NULL
, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED
);
18 require(connection
, done
);
20 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
21 if (xpc_get_type(event
) == XPC_TYPE_ERROR
) {
22 if (event
== XPC_ERROR_CONNECTION_INVALID
) {
23 syslog(LOG_ERR
, "securityd_service not available");
25 // XPC_ERROR_CONNECTION_INTERRUPTED
26 // XPC_ERROR_TERMINATION_IMMINENT
28 char * desc
= xpc_copy_description(event
);
29 syslog(LOG_ERR
, "securityd_service should never get messages on this connection: %s", desc
);
34 xpc_connection_resume(connection
);
43 _service_send_msg(service_context_t
*context
, xpc_object_t message
, xpc_object_t
* reply_out
)
45 int rc
= KB_GeneralError
;
46 xpc_object_t reply
= NULL
;
47 xpc_connection_t conn
= NULL
;
49 require(message
, done
);
50 conn
= _service_get_connection();
54 xpc_dictionary_set_data(message
, SERVICE_XPC_CONTEXT
, context
, sizeof(service_context_t
));
56 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
58 require(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
);
60 rc
= (int)xpc_dictionary_get_int64(reply
, SERVICE_XPC_RC
);
68 if (reply
) xpc_release(reply
);
73 _service_client_send_secret(service_context_t
*context
, uint64_t request
, const void * secret
, int secret_len
, const void * new_secret
, int new_secret_len
)
75 int rc
= KB_GeneralError
;
76 xpc_object_t message
= NULL
;
78 message
= xpc_dictionary_create(NULL
, NULL
, 0);
79 require_quiet(message
, done
);
81 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, request
);
83 xpc_dictionary_set_data(message
, SERVICE_XPC_SECRET
, secret
, secret_len
);
87 xpc_dictionary_set_data(message
, SERVICE_XPC_SECRET_NEW
, new_secret
, new_secret_len
);
90 rc
= _service_send_msg(context
, message
, NULL
);
93 if (message
) xpc_release(message
);
98 service_client_kb_create(service_context_t
*context
, const void * secret
, int secret_len
)
100 return _service_client_send_secret(context
, SERVICE_KB_CREATE
, secret
, secret_len
, NULL
, 0);
104 service_client_kb_load(service_context_t
*context
)
106 return _service_client_send_secret(context
, SERVICE_KB_LOAD
, NULL
, 0, NULL
, 0);
110 service_client_kb_unload(service_context_t
*context
)
112 return _service_client_send_secret(context
, SERVICE_KB_UNLOAD
, NULL
, 0, NULL
, 0);
116 service_client_kb_save(service_context_t
*context
)
118 return _service_client_send_secret(context
, SERVICE_KB_SAVE
, NULL
, 0, NULL
, 0);
122 service_client_kb_unlock(service_context_t
*context
, const void * secret
, int secret_len
)
124 return _service_client_send_secret(context
, SERVICE_KB_UNLOCK
, secret
, secret_len
, NULL
, 0);
128 service_client_kb_lock(service_context_t
*context
)
130 return _service_client_send_secret(context
, SERVICE_KB_LOCK
, NULL
, 0, NULL
, 0);
134 service_client_kb_change_secret(service_context_t
*context
, const void * secret
, int secret_len
, const void * new_secret
, int new_secret_len
)
136 return _service_client_send_secret(context
, SERVICE_KB_CHANGE_SECRET
, secret
, secret_len
, new_secret
, new_secret_len
);
140 service_client_kb_reset(service_context_t
*context
, const void * secret
, int secret_len
)
142 return _service_client_send_secret(context
, SERVICE_KB_RESET
, secret
, secret_len
, NULL
, 0);
145 int service_client_kb_is_locked(service_context_t
*context
, bool *locked
, bool *no_pin
)
147 int rc
= KB_GeneralError
;
148 xpc_object_t message
= NULL
;
149 xpc_object_t reply
= NULL
;
151 if (locked
) *locked
= false;
152 if (no_pin
) *no_pin
= false;
154 message
= xpc_dictionary_create(NULL
, NULL
, 0);
155 require_quiet(message
, done
);
157 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, SERVICE_KB_IS_LOCKED
);
159 rc
= _service_send_msg(context
, message
, &reply
);
161 if (rc
== KB_Success
) {
163 *locked
= xpc_dictionary_get_bool(reply
, SERVICE_XPC_LOCKED
);
166 *no_pin
= xpc_dictionary_get_bool(reply
, SERVICE_XPC_NO_PIN
);
171 if (message
) xpc_release(message
);
172 if (reply
) xpc_release(reply
);
177 service_client_stash_set_key(service_context_t
*context
, const void * key
, int key_len
)
179 int rc
= KB_GeneralError
;
180 xpc_object_t message
= NULL
;
182 message
= xpc_dictionary_create(NULL
, NULL
, 0);
183 require_quiet(message
, done
);
185 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, SERVICE_STASH_SET_KEY
);
188 xpc_dictionary_set_data(message
, SERVICE_XPC_KEY
, key
, key_len
);
190 rc
= _service_send_msg(context
, message
, NULL
);
193 if (message
) xpc_release(message
);
198 service_client_stash_load_key(service_context_t
*context
, const void * key
, int key_len
)
200 int rc
= KB_GeneralError
;
201 xpc_object_t message
= NULL
;
203 message
= xpc_dictionary_create(NULL
, NULL
, 0);
204 require_quiet(message
, done
);
206 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, SERVICE_STASH_LOAD_KEY
);
209 xpc_dictionary_set_data(message
, SERVICE_XPC_KEY
, key
, key_len
);
211 rc
= _service_send_msg(context
, message
, NULL
);
214 if (message
) xpc_release(message
);
219 service_client_stash_get_key(service_context_t
*context
, void ** key
, int * key_len
)
221 int rc
= KB_GeneralError
;
222 xpc_object_t message
= NULL
;
223 xpc_object_t reply
= NULL
;
226 require(key_len
, done
);
228 message
= xpc_dictionary_create(NULL
, NULL
, 0);
229 require_quiet(message
, done
);
231 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, SERVICE_STASH_GET_KEY
);
233 rc
= _service_send_msg(context
, message
, &reply
);
235 if (rc
== KB_Success
) {
237 const void * data
= xpc_dictionary_get_data(reply
, SERVICE_XPC_KEY
, &data_len
);
239 *key
= calloc(1u, data_len
);
240 memcpy(*key
, data
, data_len
);
241 *key_len
= (int)data_len
;
246 if (message
) xpc_release(message
);
247 if (reply
) xpc_release(reply
);