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(context
, done
);
50 require(message
, done
);
51 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_save(service_context_t
*context
)
112 return _service_client_send_secret(context
, SERVICE_KB_SAVE
, NULL
, 0, NULL
, 0);
116 service_client_kb_unlock(service_context_t
*context
, const void * secret
, int secret_len
)
118 return _service_client_send_secret(context
, SERVICE_KB_UNLOCK
, secret
, secret_len
, NULL
, 0);
122 service_client_kb_lock(service_context_t
*context
)
124 return _service_client_send_secret(context
, SERVICE_KB_LOCK
, NULL
, 0, NULL
, 0);
128 service_client_kb_change_secret(service_context_t
*context
, const void * secret
, int secret_len
, const void * new_secret
, int new_secret_len
)
130 return _service_client_send_secret(context
, SERVICE_KB_CHANGE_SECRET
, secret
, secret_len
, new_secret
, new_secret_len
);
134 service_client_kb_reset(service_context_t
*context
, const void * secret
, int secret_len
)
136 return _service_client_send_secret(context
, SERVICE_KB_RESET
, secret
, secret_len
, NULL
, 0);
139 int service_client_kb_is_locked(service_context_t
*context
, bool *locked
, bool *no_pin
)
141 int rc
= KB_GeneralError
;
142 xpc_object_t message
= NULL
;
143 xpc_object_t reply
= NULL
;
145 if (locked
) *locked
= false;
146 if (no_pin
) *no_pin
= false;
148 message
= xpc_dictionary_create(NULL
, NULL
, 0);
149 require_quiet(message
, done
);
151 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, SERVICE_KB_IS_LOCKED
);
153 rc
= _service_send_msg(context
, message
, &reply
);
155 if (rc
== KB_Success
) {
157 *locked
= xpc_dictionary_get_bool(reply
, SERVICE_XPC_LOCKED
);
160 *no_pin
= xpc_dictionary_get_bool(reply
, SERVICE_XPC_NO_PIN
);
165 if (message
) xpc_release(message
);
166 if (reply
) xpc_release(reply
);
171 service_client_stash_set_key(service_context_t
*context
, const void * key
, int key_len
)
173 int rc
= KB_GeneralError
;
174 xpc_object_t message
= NULL
;
176 message
= xpc_dictionary_create(NULL
, NULL
, 0);
177 require_quiet(message
, done
);
179 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, SERVICE_STASH_SET_KEY
);
182 xpc_dictionary_set_data(message
, SERVICE_XPC_KEY
, key
, key_len
);
184 rc
= _service_send_msg(context
, message
, NULL
);
187 if (message
) xpc_release(message
);
192 service_client_stash_load_key(service_context_t
*context
, const void * key
, int key_len
)
194 int rc
= KB_GeneralError
;
195 xpc_object_t message
= NULL
;
197 message
= xpc_dictionary_create(NULL
, NULL
, 0);
198 require_quiet(message
, done
);
200 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, SERVICE_STASH_LOAD_KEY
);
203 xpc_dictionary_set_data(message
, SERVICE_XPC_KEY
, key
, key_len
);
205 rc
= _service_send_msg(context
, message
, NULL
);
208 if (message
) xpc_release(message
);
213 service_client_stash_get_key(service_context_t
*context
, void ** key
, int * key_len
)
215 int rc
= KB_GeneralError
;
216 xpc_object_t message
= NULL
;
217 xpc_object_t reply
= NULL
;
220 require(key_len
, done
);
222 message
= xpc_dictionary_create(NULL
, NULL
, 0);
223 require_quiet(message
, done
);
225 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, SERVICE_STASH_GET_KEY
);
227 rc
= _service_send_msg(context
, message
, &reply
);
229 if (rc
== KB_Success
) {
231 const void * data
= xpc_dictionary_get_data(reply
, SERVICE_XPC_KEY
, &data_len
);
233 *key
= calloc(1u, data_len
);
234 memcpy(*key
, data
, data_len
);
235 *key_len
= (int)data_len
;
240 if (message
) xpc_release(message
);
241 if (reply
) xpc_release(reply
);