1 /* Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. */
3 #include "securityd_service.h"
4 #include "securityd_service_client.h"
10 #include <xpc/private.h>
11 #include <dispatch/dispatch.h>
12 #include <sys/types.h>
14 #include <sys/codesign.h>
21 #include <uuid/uuid.h>
22 #include <bsm/libbsm.h>
24 #include <AssertMacros.h>
25 #include <Security/Security.h>
26 #include <Security/SecTask.h>
27 #include <Security/SecTaskPriv.h>
28 #include <Security/SecKeychainPriv.h>
29 #include <MobileKeyBag/MobileKeyBag.h>
31 #include <IOKit/IOKitLib.h>
32 #include <Kernel/IOKit/crypto/AppleFDEKeyStoreDefs.h>
34 #define LOG(...) os_log_debug(OS_LOG_DEFAULT, ##__VA_ARGS__);
36 static bool check_signature(xpc_connection_t connection
);
38 static pid_t
get_caller_pid(audit_token_t
* token
)
42 audit_token_to_au32(*token
, NULL
, NULL
, NULL
, NULL
, NULL
, &pid
, NULL
, NULL
);
47 // exported from libaks.a
48 kern_return_t
aks_register_for_notifications(mach_port_t server_port
, uintptr_t message_id
);
49 kern_return_t
aks_stash_escrow(keybag_handle_t handle
, bool create
, const void * secret
, int secret_len
, const void * in_data
, int in_data_len
, void ** out_data
, int * out_data_len
);
51 const char * kb_home_path
= "Library/Keychains";
52 const char * kb_user_bag
= "user.kb";
53 const char * kb_stash_bag
= "stash.kb";
55 #define HEXBUF_LEN 2048
62 } service_user_record_t
;
72 io_registry_entry_t service
;
76 service
= IOServiceGetMatchingService(kIOMasterPortDefault
, IOServiceMatching(kAppleFDEKeyStoreServiceName
));
77 if (service
== IO_OBJECT_NULL
)
78 return IO_OBJECT_NULL
;
80 kr
= IOServiceOpen(service
, mach_task_self(), 0, &conn
);
81 if (kr
!= KERN_SUCCESS
)
82 return IO_OBJECT_NULL
;
84 kr
= IOConnectCallMethod(conn
, kAppleFDEKeyStoreUserClientOpen
, NULL
, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
85 if (kr
!= KERN_SUCCESS
) {
87 return IO_OBJECT_NULL
;
94 closeiodev(io_connect_t conn
)
97 kr
= IOConnectCallMethod(conn
, kAppleFDEKeyStoreUserClientClose
, NULL
, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
98 if (kr
!= KERN_SUCCESS
)
100 IOServiceClose(conn
);
103 static dispatch_queue_t
104 _kb_service_get_dispatch_queue()
106 static dispatch_once_t onceToken
= 0;
107 static dispatch_queue_t connection_queue
= NULL
;
109 dispatch_once(&onceToken
, ^{
110 connection_queue
= dispatch_queue_create("kb-service-queue", DISPATCH_QUEUE_SERIAL
);
113 return connection_queue
;
116 static service_user_record_t
* get_user_record(uid_t uid
)
118 service_user_record_t
* ur
= NULL
;
120 if ((bufsize
= sysconf(_SC_GETPW_R_SIZE_MAX
)) == -1) {
124 struct passwd pwbuf
, *pw
= NULL
;
126 if (((rc
= getpwuid_r(uid
, &pwbuf
, buf
, bufsize
, &pw
)) == 0) && pw
!= NULL
) {
127 ur
= calloc(1u, sizeof(service_user_record_t
));
129 ur
->uid
= pw
->pw_uid
;
130 ur
->gid
= pw
->pw_gid
;
131 ur
->home
= strdup(pw
->pw_dir
);
132 ur
->name
= strdup(pw
->pw_name
);
134 os_log(OS_LOG_DEFAULT
, "failed (%d) to lookup user record for uid: %d", rc
, uid
);
141 static void free_user_record(service_user_record_t
* ur
)
154 static const char * get_host_uuid()
156 static uuid_string_t hostuuid
= {};
157 static dispatch_once_t onceToken
;
158 dispatch_once(&onceToken
, ^{
159 struct timespec timeout
= {30, 0};
161 if (gethostuuid(uuid
, &timeout
) == 0) {
162 uuid_unparse(uuid
, hostuuid
);
164 os_log(OS_LOG_DEFAULT
, "failed to get host uuid");
173 _kb_copy_bag_filename(service_user_record_t
* ur
, kb_bag_type_t type
)
175 char * bag_file
= NULL
;
176 const char * name
= NULL
;
180 case kb_bag_type_user
:
183 case kb_bag_type_stash
:
190 bag_file
= calloc(1u, PATH_MAX
);
191 require(bag_file
, done
);
193 snprintf(bag_file
, PATH_MAX
, "%s/%s/%s/%s", ur
->home
, kb_home_path
, get_host_uuid(), name
);
200 _kb_verify_create_path(service_user_record_t
* ur
)
202 bool created
= false;
203 struct stat st_info
= {};
204 char new_path
[PATH_MAX
] = {};
205 char kb_path
[PATH_MAX
] = {};
206 snprintf(kb_path
, sizeof(kb_path
), "%s/%s/%s", ur
->home
, kb_home_path
, get_host_uuid());
207 if (lstat(kb_path
, &st_info
) == 0) {
208 if (S_ISDIR(st_info
.st_mode
)) {
211 os_log(OS_LOG_DEFAULT
, "invalid directory at '%s' moving aside", kb_path
);
212 snprintf(new_path
, sizeof(new_path
), "%s-invalid", kb_path
);
214 if (rename(kb_path
, new_path
) != 0) {
215 os_log(OS_LOG_DEFAULT
, "failed to rename file: %s (%s)", kb_path
, strerror(errno
));
221 require_action(mkpath_np(kb_path
, 0700) == 0, done
, os_log(OS_LOG_DEFAULT
, "could not create path: %s (%s)", kb_path
, strerror(errno
)));
227 os_log(OS_LOG_DEFAULT
, "_kb_verify_create_path failed %s", kb_path
);
233 _set_thread_credentials(service_user_record_t
* ur
)
235 int rc
= pthread_setugid_np(ur
->uid
, ur
->gid
);
236 if (rc
) { os_log(OS_LOG_DEFAULT
, "failed to set thread credential: %i (%s)", errno
, strerror(errno
)); }
238 rc
= initgroups(ur
->name
, ur
->gid
);
239 if (rc
) { os_log(OS_LOG_DEFAULT
, "failed to initgroups: %i", rc
); }
243 _clear_thread_credentials()
245 int rc
= pthread_setugid_np(KAUTH_UID_NONE
, KAUTH_GID_NONE
);
246 if (rc
) { os_log(OS_LOG_DEFAULT
, "failed to reset thread credential: %i (%s)", errno
, strerror(errno
)); }
250 _kb_bag_exists(service_user_record_t
* ur
, const char * bag_file
)
253 struct stat st_info
= {};
254 char new_file
[PATH_MAX
] = {};
258 _set_thread_credentials(ur
);
259 if (lstat(bag_file
, &st_info
) == 0) {
260 if (S_ISREG(st_info
.st_mode
)) {
263 os_log(OS_LOG_DEFAULT
, "invalid file at '%s' moving aside", bag_file
);
264 snprintf(new_file
, sizeof(new_file
), "%s-invalid", bag_file
);
266 if (rename(bag_file
, new_file
) != 0) {
267 os_log(OS_LOG_DEFAULT
, "failed to rename file: %s (%s)", bag_file
, strerror(errno
));
273 _clear_thread_credentials();
278 _kb_save_bag_to_disk(service_user_record_t
* ur
, const char * bag_file
, void * data
, size_t length
)
283 require(bag_file
, done
);
285 _set_thread_credentials(ur
);
286 require(_kb_verify_create_path(ur
), done
);
288 fd
= open(bag_file
, O_CREAT
| O_TRUNC
| O_WRONLY
| O_NOFOLLOW
, 0600);
289 require_action(fd
!= -1, done
, os_log(OS_LOG_DEFAULT
, "could not create file: %s (%s)", bag_file
, strerror(errno
)));
290 require_action(write(fd
, data
, length
) == length
, done
, os_log(OS_LOG_DEFAULT
, "failed to write keybag to disk %s (%s)", bag_file
, strerror(errno
)));
295 if (fd
!= -1) { close(fd
); }
296 _clear_thread_credentials();
301 _kb_load_bag_from_disk(service_user_record_t
* ur
, const char * bag_file
, uint8_t ** data
, size_t * length
)
305 uint8_t * buf
= NULL
;
307 struct stat st_info
= {};
309 require(bag_file
, done
);
311 _set_thread_credentials(ur
);
312 require(_kb_verify_create_path(ur
), done
);
313 require_action_quiet(lstat(bag_file
, &st_info
) == 0, done
, os_log(OS_LOG_DEFAULT
, "failed to stat file: %s (%s)", bag_file
, strerror(errno
)));
314 require_action(S_ISREG(st_info
.st_mode
), done
, os_log(OS_LOG_DEFAULT
, "failed to load, not a file: %s", bag_file
));
315 buf_size
= (size_t)st_info
.st_size
;
317 fd
= open(bag_file
, O_RDONLY
| O_NOFOLLOW
);
318 require_action(fd
!= -1, done
, os_log(OS_LOG_DEFAULT
, "could not open file: %s (%s)", bag_file
, strerror(errno
)));
320 buf
= (uint8_t *)calloc(1u, buf_size
);
321 require(buf
!= NULL
, done
);
322 require(read(fd
, buf
, buf_size
) == buf_size
, done
);
330 if (fd
!= -1) { close(fd
); }
331 if (buf
) { free(buf
); }
332 _clear_thread_credentials();
337 _kb_rename_bag_on_disk(service_user_record_t
* ur
, const char * bag_file
)
339 char new_file
[PATH_MAX
] = {};
341 _set_thread_credentials(ur
);
342 snprintf(new_file
, sizeof(new_file
), "%s-invalid", bag_file
);
344 rename(bag_file
, new_file
);
345 _clear_thread_credentials();
350 _kb_delete_bag_on_disk(service_user_record_t
* ur
, const char * bag_file
)
353 _set_thread_credentials(ur
);
355 _clear_thread_credentials();
359 static int service_kb_load(service_context_t
*context
);
360 static int service_kb_load_uid(uid_t s_uid
);
362 #ifndef AKS_MACOS_ROOT_HANDLE
363 #define AKS_MACOS_ROOT_HANDLE 4 //temporary define to avoid dependency on AKS change, filed rdar://problem/30542034
364 #endif /* AKS_MACOS_ROOT_HANDLE */
367 _service_kb_set_system(keybag_handle_t handle
, keybag_handle_t special_handle
)
369 //Use reserved root handle for root sessions, since 0 clashes with device_keybag_handle in AKS
370 return aks_set_system(handle
, (special_handle
== 0) ? AKS_MACOS_ROOT_HANDLE
: special_handle
);
374 _service_kb_get_system(keybag_handle_t special_handle
, keybag_handle_t
* handle_out
)
376 //Use reserved root handle for root sessions, since 0 clashes with device_keybag_handle in AKS
377 return aks_get_system((special_handle
== 0) ? AKS_MACOS_ROOT_HANDLE
: special_handle
, handle_out
);
381 _kb_get_session_handle(service_context_t
* context
, keybag_handle_t
* handle_out
)
383 int rc
= KB_BagNotLoaded
;
384 require_noerr_quiet(_service_kb_get_system(context
->s_uid
, handle_out
), done
);
389 if (rc
== KB_BagNotLoaded
) {
390 if (service_kb_load(context
) == KB_Success
) {
391 if (_service_kb_get_system(context
->s_uid
, handle_out
) == kIOReturnSuccess
) {
399 static void update_keybag_handle(keybag_handle_t handle
)
401 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
402 uid_t uid
= abs(handle
);
403 uint8_t * buf
= NULL
;
405 service_user_record_t
* ur
= NULL
;
406 char * bag_file
= NULL
;
408 require_noerr(aks_save_bag(handle
, (void**)&buf
, (int*)&buf_size
), done
);
409 require(ur
= get_user_record(uid
), done
);
410 require(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
);
411 require(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
), done
);
413 os_log(OS_LOG_DEFAULT
, "successfully updated handle %d", handle
);
417 if (ur
) free_user_record(ur
);
418 if (bag_file
) free(bag_file
);
423 _kb_get_options_for_uid(uid_t uid
, CFMutableDictionaryRef
*options_out
)
425 int result
= KB_GeneralError
;
426 CFMutableDictionaryRef options
= NULL
;
427 CFNumberRef cf_uid
= NULL
;
429 require(options_out
, out
);
431 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), out
);
432 require(cf_uid
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &uid
), out
);
433 CFDictionaryAddValue(options
, kKeyBagDeviceHandle
, cf_uid
);
435 *options_out
= options
;
440 if (options
) { CFRelease(options
); }
441 if (cf_uid
) { CFRelease(cf_uid
); }
447 _kb_set_user_uuid(service_context_t
* context
, const void * secret
, int secret_len
)
449 int result
= KB_GeneralError
;
450 CFMutableDictionaryRef options
= NULL
;
451 CFDataRef passcode
= NULL
;
453 require_noerr(_kb_get_options_for_uid(context
->s_uid
, &options
), done
);
455 /* set user uuid, if not already set */
456 passcode
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, secret
, secret_len
, kCFAllocatorNull
);
457 MKBKeyBagSetUserUUID(options
, passcode
);
461 if (options
) { CFRelease(options
); }
462 if (passcode
) { CFRelease(passcode
); }
467 service_kb_create(service_context_t
* context
, const void * secret
, int secret_len
)
469 __block
int rc
= KB_GeneralError
;
471 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
472 uint8_t * buf
= NULL
;
474 keybag_handle_t private_handle
= bad_keybag_handle
, session_handle
= bad_keybag_handle
;
475 service_user_record_t
* ur
= get_user_record(context
->s_uid
);
476 char * bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_user
);
478 require(bag_file
, done
);
480 // check for the existance of the bagfile
481 require_action(!_kb_bag_exists(ur
, bag_file
), done
, rc
= KB_BagExists
);
483 require_noerr(rc
= aks_create_bag(secret
, secret_len
, kAppleKeyStoreDeviceBag
, &private_handle
), done
);
484 require_noerr(rc
= aks_save_bag(private_handle
, (void**)&buf
, (int*)&buf_size
), done
);
485 require_action(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
), done
, rc
= KB_BagError
);
486 require_noerr(rc
= _service_kb_set_system(private_handle
, context
->s_uid
), done
);
487 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
489 if (secret
&& rc
== KB_Success
) {
490 aks_unlock_bag(session_handle
, secret
, secret_len
);
493 if (rc
== KB_Success
) {
494 _kb_set_user_uuid(context
, secret
, secret_len
);
498 if (private_handle
!= bad_keybag_handle
) {
499 aks_unload_bag(private_handle
);
502 if (bag_file
) { free(bag_file
); }
503 if (ur
) free_user_record(ur
);
509 /* Load s_uid's keybag, unless already loaded */
511 _service_kb_load_uid(uid_t s_uid
)
513 __block
int rc
= KB_GeneralError
;
515 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
516 uint8_t * buf
= NULL
;
518 keybag_handle_t private_handle
= bad_keybag_handle
, session_handle
= bad_keybag_handle
;
519 service_user_record_t
* ur
= NULL
;
520 char * bag_file
= NULL
;
523 rc
= _service_kb_get_system(s_uid
, &session_handle
);
524 if (rc
== kIOReturnNotFound
) {
525 require_action(ur
= get_user_record(s_uid
), done
, rc
= KB_GeneralError
; _stage
= 1);
526 require_action(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
, rc
= KB_GeneralError
; _stage
= 2);
527 require_action_quiet(_kb_load_bag_from_disk(ur
, bag_file
, &buf
, &buf_size
), done
, rc
= KB_BagNotFound
; _stage
= 3);
528 rc
= aks_load_bag(buf
, (int)buf_size
, &private_handle
);
529 if (rc
== kIOReturnNotPermitted
|| rc
== kAKSReturnBadDeviceKey
) {
530 os_log(OS_LOG_DEFAULT
, "bag load failed %d for uid (%i)", rc
, s_uid
);
531 _kb_rename_bag_on_disk(ur
, bag_file
);
534 require_noerr(rc
, done
; _stage
= 4);
535 require_noerr(rc
= _service_kb_set_system(private_handle
, s_uid
), done
; _stage
= 5);
537 require(rc
== KB_Success
, done
);
540 if (private_handle
!= bad_keybag_handle
) {
541 aks_unload_bag(private_handle
);
543 // this function should never fail unless bootstrapping the user for the first time, or rare conditions from aks_load_bag
544 if (rc
!= KB_Success
) {
545 os_log(OS_LOG_DEFAULT
, "%d: error %d loading keybag for uid (%i) at path: %s", _stage
, rc
, s_uid
, bag_file
);
548 if (ur
) free_user_record(ur
);
549 if (bag_file
) free(bag_file
);
556 service_kb_load_uid(uid_t s_uid
)
558 return _service_kb_load_uid(s_uid
);
562 service_kb_load(service_context_t
* context
)
564 return _service_kb_load_uid(context
->s_uid
);
568 service_kb_unload(service_context_t
*context
)
570 __block
int rc
= KB_GeneralError
;
572 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
573 keybag_handle_t session_handle
= bad_keybag_handle
;
575 rc
= _service_kb_get_system(context
->s_uid
, &session_handle
);
576 if (rc
== kIOReturnNotFound
) {
577 // No session bag, nothing to do
580 } else if (rc
!= kIOReturnSuccess
) {
581 os_log(OS_LOG_DEFAULT
, "error locating session keybag for uid (%i) in session (%i)", context
->s_uid
, context
->s_id
);
586 rc
= aks_unload_bag(session_handle
);
587 if (rc
!= kAKSReturnSuccess
) {
588 os_log(OS_LOG_DEFAULT
, "error unloading keybag for uid (%i) in session (%i)", context
->s_uid
, context
->s_id
);
591 os_log(OS_LOG_DEFAULT
, "successfully unloaded keybag (%ld) for uid (%i) in session (%i)", (long)session_handle
, context
->s_uid
, context
->s_id
);
599 service_kb_save(service_context_t
* context
)
601 __block
int rc
= KB_GeneralError
;
602 keybag_handle_t session_handle
;
603 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
605 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
606 uint8_t * buf
= NULL
;
608 service_user_record_t
* ur
= NULL
;
609 char * bag_file
= NULL
;
611 require_noerr(rc
= aks_save_bag(session_handle
, (void**)&buf
, (int*)&buf_size
), done
);
612 require_action(ur
= get_user_record(context
->s_uid
), done
, rc
= KB_GeneralError
);
613 require_action(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
, rc
= KB_GeneralError
);
614 require_action(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
), done
, rc
= KB_BagError
);
620 if (ur
) free_user_record(ur
);
621 if (bag_file
) free(bag_file
);
630 service_kb_unlock(service_context_t
* context
, const void * secret
, int secret_len
)
632 int rc
= KB_GeneralError
;
633 keybag_handle_t session_handle
;
634 CFDataRef passcode
= NULL
;
635 CFMutableDictionaryRef options
= NULL
;
637 require_noerr(_kb_get_options_for_uid(context
->s_uid
, &options
), done
);
639 /* technically, session_handle is not needed. Call this to handle lazy keybag loading */
640 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
642 require(passcode
= CFDataCreateWithBytesNoCopy(NULL
, secret
, secret_len
, kCFAllocatorNull
), done
);
644 rc
= MKBUnlockDevice(passcode
, options
);
645 os_log(OS_LOG_DEFAULT
, "MKBUnlockDevice result: (%ld)", (long)rc
);
648 if (options
) { CFRelease(options
); }
649 if (passcode
) { CFRelease(passcode
); }
654 service_kb_lock(service_context_t
* context
)
656 // this call has been disabled
661 service_kb_change_secret(service_context_t
* context
, const void * secret
, int secret_len
, const void * new_secret
, int new_secret_len
)
663 __block
int rc
= KB_GeneralError
;
664 keybag_handle_t session_handle
;
665 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
667 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
668 uint8_t * buf
= NULL
;
670 service_user_record_t
* ur
= NULL
;
671 char * bag_file
= NULL
;
673 require_noerr(rc
= aks_change_secret(session_handle
, secret
, secret_len
, new_secret
, new_secret_len
, generation_noop
, NULL
), done
);
674 require_noerr(rc
= aks_save_bag(session_handle
, (void**)&buf
, (int*)&buf_size
), done
);
675 require_action(ur
= get_user_record(context
->s_uid
), done
, rc
= KB_GeneralError
);
676 require_action(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
, rc
= KB_GeneralError
);
677 require_action(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
), done
, rc
= KB_BagError
);
683 if (ur
) free_user_record(ur
);
684 if (bag_file
) free(bag_file
);
693 service_kb_reset(service_context_t
* context
, const void * secret
, int secret_len
)
695 __block
int rc
= KB_GeneralError
;
696 service_user_record_t
* ur
= NULL
;
697 char * bag_file
= NULL
;
699 require_action(ur
= get_user_record(context
->s_uid
), done
, rc
= KB_GeneralError
);
700 require_action(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
, rc
= KB_GeneralError
);
702 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
703 uint8_t * buf
= NULL
;
705 keybag_handle_t private_handle
= bad_keybag_handle
, session_handle
= bad_keybag_handle
;
707 os_log(OS_LOG_DEFAULT
, "resetting keybag for uid (%i) in session (%i)", context
->s_uid
, context
->s_id
);
708 _kb_rename_bag_on_disk(ur
, bag_file
);
710 require_noerr(rc
= aks_create_bag(secret
, secret_len
, kAppleKeyStoreDeviceBag
, &private_handle
), done
);
711 require_noerr(rc
= aks_save_bag(private_handle
, (void**)&buf
, (int*)&buf_size
), done
);
712 require_action(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
), done
, rc
= KB_BagError
);
713 require_noerr(rc
= _service_kb_set_system(private_handle
, context
->s_uid
), done
);
714 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
716 if (secret
&& rc
== KB_Success
) {
717 aks_unlock_bag(session_handle
, secret
, secret_len
);
720 if (rc
== KB_Success
) {
721 _kb_set_user_uuid(context
, secret
, secret_len
);
725 if (private_handle
!= bad_keybag_handle
) {
726 aks_unload_bag(private_handle
);
733 if (ur
) free_user_record(ur
);
734 if (bag_file
) free(bag_file
);
739 service_kb_is_locked(service_context_t
* context
, xpc_object_t reply
)
741 int rc
= KB_GeneralError
;
742 keybag_state_t state
;
743 keybag_handle_t session_handle
;
744 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
746 require_noerr(rc
= aks_get_lock_state(session_handle
, &state
), done
);
748 xpc_dictionary_set_bool(reply
, SERVICE_XPC_LOCKED
, state
& keybag_state_locked
);
749 xpc_dictionary_set_bool(reply
, SERVICE_XPC_NO_PIN
, state
& keybag_state_no_pin
);
756 service_kb_wrap_key(service_context_t
*context
, xpc_object_t event
, xpc_object_t reply
)
758 int rc
= KB_GeneralError
;
762 keyclass_t key_class
;
763 keybag_handle_t session_handle
;
764 void *wrapped_key
= NULL
;
765 int wrapped_key_size
;
766 keyclass_t wrapped_key_class
;
768 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
770 key
= xpc_dictionary_get_data(event
, SERVICE_XPC_KEY
, &sz
);
771 require_action(key
!= NULL
, done
, rc
= KB_GeneralError
);
772 require_action(sz
<= APPLE_KEYSTORE_MAX_KEY_LEN
, done
, rc
= KB_GeneralError
);
774 key_class
= (keyclass_t
)xpc_dictionary_get_int64(event
, SERVICE_XPC_KEYCLASS
);
776 wrapped_key_size
= APPLE_KEYSTORE_MAX_ASYM_WRAPPED_KEY_LEN
;
777 wrapped_key
= calloc(1, wrapped_key_size
);
779 rc
= aks_wrap_key(key
, key_size
, key_class
, session_handle
, wrapped_key
, &wrapped_key_size
, &wrapped_key_class
);
780 if (rc
== KB_Success
) {
781 xpc_dictionary_set_data(reply
, SERVICE_XPC_WRAPPED_KEY
, wrapped_key
, wrapped_key_size
);
782 xpc_dictionary_set_int64(reply
, SERVICE_XPC_KEYCLASS
, wrapped_key_class
);
791 service_kb_unwrap_key(service_context_t
*context
, xpc_object_t event
, xpc_object_t reply
)
793 int rc
= KB_GeneralError
;
795 const void *wrapped_key
;
796 int wrapped_key_size
;
797 keyclass_t wrapped_key_class
;
798 keybag_handle_t session_handle
;
802 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
804 wrapped_key
= xpc_dictionary_get_data(event
, SERVICE_XPC_WRAPPED_KEY
, &sz
);
805 require_action(wrapped_key
!= NULL
, done
, rc
= KB_GeneralError
);
806 require_action(sz
<= APPLE_KEYSTORE_MAX_ASYM_WRAPPED_KEY_LEN
, done
, rc
= KB_GeneralError
);
807 wrapped_key_size
= (int)sz
;
808 wrapped_key_class
= (keyclass_t
)xpc_dictionary_get_int64(event
, SERVICE_XPC_KEYCLASS
);
810 key_size
= APPLE_KEYSTORE_MAX_KEY_LEN
;
811 key
= calloc(1, key_size
);
813 rc
= aks_unwrap_key(wrapped_key
, wrapped_key_size
, wrapped_key_class
, session_handle
, key
, &key_size
);
814 if (rc
== KB_Success
) {
815 xpc_dictionary_set_data(reply
, SERVICE_XPC_KEY
, key
, key_size
);
824 service_kb_stash_create(service_context_t
* context
, const void * key
, unsigned key_size
)
826 int rc
= KB_GeneralError
;
827 char * bag_file
= NULL
;
828 keybag_handle_t session_handle
;
829 service_user_record_t
* ur
= NULL
;
830 void * stashbag
= NULL
;
831 int stashbag_size
= 0;
832 __block
bool saved
= false;
835 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
836 require_action(ur
= get_user_record(context
->s_uid
), done
, rc
= KB_GeneralError
);
837 require_noerr(rc
= aks_stash_escrow(session_handle
, true, key
, key_size
, NULL
, 0, (void**)&stashbag
, &stashbag_size
), done
);
838 require_action(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_stash
), done
, rc
= KB_GeneralError
);
840 // sync writing the bag to disk
841 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
842 saved
= _kb_save_bag_to_disk(ur
, bag_file
, stashbag
, stashbag_size
);
844 require_action(saved
, done
, rc
= KB_BagError
);
848 if (stashbag
) { free(stashbag
); }
849 if (bag_file
) { free(bag_file
); }
850 if (ur
) free_user_record(ur
);
855 service_kb_stash_load(service_context_t
* context
, const void * key
, unsigned key_size
, bool nondestructive
)
857 __block
int rc
= KB_GeneralError
;
858 char * bag_file
= NULL
;
859 keybag_handle_t session_handle
;
860 service_user_record_t
* ur
= NULL
;
861 __block
uint8_t * stashbag
= NULL
;
862 __block
size_t stashbag_size
= 0;
865 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
866 require_action(ur
= get_user_record(context
->s_uid
), done
, rc
= KB_GeneralError
);
867 require_action(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_stash
), done
, rc
= KB_GeneralError
);
869 // sync loading the bag from disk
870 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
871 if (!_kb_load_bag_from_disk(ur
, bag_file
, &stashbag
, &stashbag_size
)) {
875 require_noerr(rc
, done
);
877 require_noerr(rc
= aks_stash_escrow(session_handle
, false, key
, key_size
, stashbag
, (int)stashbag_size
, NULL
, NULL
), done
);
881 if (stashbag
) { free(stashbag
); }
882 if ((bag_file
) && (!nondestructive
)) {
883 _kb_delete_bag_on_disk(ur
, bag_file
);
886 if (ur
) free_user_record(ur
);
891 // Get the keychain master key from the AppleFDEKeyStore.
892 // Note that this is a one-time call - the master key is
893 // removed from the keystore after it is returned.
894 // Requires the entitlement: com.apple.private.securityd.keychain
896 OSStatus
service_stash_get_key(service_context_t
* context
, xpc_object_t event
, xpc_object_t reply
)
898 getStashKey_InStruct_t inStruct
;
899 getStashKey_OutStruct_t outStruct
;
900 size_t outSize
= sizeof(outStruct
);
901 kern_return_t kr
= KERN_INVALID_ARGUMENT
;
903 io_connect_t conn
= openiodev();
905 inStruct
.type
= kAppleFDEKeyStoreStash_master
;
907 kr
= IOConnectCallMethod(conn
, kAppleFDEKeyStore_getStashKey
,
909 &inStruct
, sizeof(inStruct
),
911 &outStruct
, &outSize
);
913 if (kr
== KERN_SUCCESS
) {
914 xpc_dictionary_set_data(reply
, SERVICE_XPC_KEY
, outStruct
.outBuf
.key
.key
, outStruct
.outBuf
.key
.keysize
);
915 service_kb_stash_load(context
, outStruct
.outBuf
.key
.key
, outStruct
.outBuf
.key
.keysize
, false);
917 os_log(OS_LOG_DEFAULT
, "failed to get stash key: %d", (int)kr
);
928 // Stash the keychain master key in the AppleFDEKeyStore and
929 // flag it as the keychain master key to be added to the
930 // reboot NVRAM blob.
931 // This requires two calls to the AKS: the first to store the
932 // key and get its uuid. The second uses the uuid to flag the
933 // key for blob inclusion.
935 OSStatus
service_stash_set_key(service_context_t
* context
, xpc_object_t event
, xpc_object_t reply
)
937 kern_return_t kr
= KERN_INVALID_ARGUMENT
;
938 io_connect_t conn
= IO_OBJECT_NULL
;
939 size_t keydata_len
= 0;
942 keybag_state_t state
;
943 keybag_handle_t session_handle
;
944 require_noerr(_kb_get_session_handle(context
, &session_handle
), done
);
945 require_noerr(aks_get_lock_state(session_handle
, &state
), done
);
946 require_action(!(state
& keybag_lock_locked
), done
, kr
= CSSMERR_CSP_OS_ACCESS_DENIED
; LOG("stash failed keybag locked"));
951 // Store the key in the keystore and get its uuid
952 setKeyGetUUID_InStruct_t inStruct1
;
953 uuid_OutStruct_t outStruct1
;
956 const uint8_t *keydata
= xpc_dictionary_get_data(event
, SERVICE_XPC_KEY
, &keydata_len
);
957 require(keydata
, done
);
959 memcpy(&inStruct1
.inKey
.key
.key
, keydata
, keydata_len
);
960 inStruct1
.inKey
.key
.keysize
= (cryptosize_t
) keydata_len
;
961 len
= sizeof(outStruct1
);
962 kr
= IOConnectCallMethod(conn
, kAppleFDEKeyStore_setKeyGetUUID
,
964 &inStruct1
, sizeof(inStruct1
),
967 require(kr
== KERN_SUCCESS
, done
);
969 // Now using the uuid stash it as the master key
970 setStashKey_InStruct_t inStruct2
;
971 memcpy(&inStruct2
.uuid
, &outStruct1
.uuid
, sizeof(outStruct1
.uuid
));
972 inStruct2
.type
= kAppleFDEKeyStoreStash_master
;
974 kr
= IOConnectCallMethod(conn
, kAppleFDEKeyStore_setStashKey
,
976 &inStruct2
, sizeof(inStruct2
),
980 if (kr
== KERN_SUCCESS
) {
981 service_kb_stash_create(context
, keydata
, (unsigned)keydata_len
);
984 os_log(OS_LOG_DEFAULT
, "set stashkey %d", (int)kr
);
993 // Load the master stash key
995 OSStatus
service_stash_load_key(service_context_t
* context
, xpc_object_t event
, xpc_object_t reply
)
997 kern_return_t kr
= KERN_SUCCESS
;
998 size_t keydata_len
= 0;
1000 const uint8_t *keydata
= xpc_dictionary_get_data(event
, SERVICE_XPC_KEY
, &keydata_len
);
1001 require(keydata
, done
);
1003 kr
= service_kb_stash_load(context
, keydata
, (cryptosize_t
) keydata_len
, true);
1010 // Signal the AppleFDEKeyStore to take the tagged FDE key
1011 // and keychain master key, stash them in an encrypted
1012 // blob structure and write the blob to NVRAM. The random
1013 // encryption key is written to the SMC.
1016 OSStatus
service_stash_blob(xpc_object_t event
, xpc_object_t reply
)
1018 kern_return_t kr
= KERN_INVALID_ARGUMENT
;
1020 io_connect_t conn
= openiodev();
1021 require(conn
, done
);
1023 kr
= IOConnectCallMethod(conn
, kAppleFDEKeyStore_commitStash
,
1036 bool peer_has_entitlement(xpc_connection_t peer
, const char * entitlement
)
1038 bool entitled
= false;
1040 xpc_object_t value
= xpc_connection_copy_entitlement_value(peer
, entitlement
);
1041 if (value
&& (xpc_get_type(value
) == XPC_TYPE_BOOL
)) {
1042 entitled
= xpc_bool_get_value(value
);
1045 if (value
) xpc_release(value
);
1049 static char * sel_to_char(uint64_t sel
)
1052 case SERVICE_STASH_SET_KEY
:
1054 case SERVICE_STASH_GET_KEY
:
1056 case SERVICE_STASH_BLOB
:
1057 return "stash_blob";
1058 case SERVICE_KB_LOAD
:
1060 case SERVICE_KB_SAVE
:
1062 case SERVICE_KB_UNLOCK
:
1064 case SERVICE_KB_LOCK
:
1066 case SERVICE_KB_CHANGE_SECRET
:
1067 return "kb_change_secret";
1068 case SERVICE_KB_CREATE
:
1070 case SERVICE_KB_IS_LOCKED
:
1071 return "kb_is_locked";
1072 case SERVICE_KB_RESET
:
1074 case SERVICE_KB_UNLOAD
:
1076 case SERVICE_KB_LOAD_UID
:
1077 return "kb_load_uid";
1078 case SERVICE_KB_WRAP_KEY
:
1079 return "kb_wrap_key";
1080 case SERVICE_KB_UNWRAP_KEY
:
1081 return "kb_unwrap_key";
1087 static char * err_to_char(int err
)
1092 case KB_GeneralError
:
1093 return "general error";
1094 case KB_BagNotFound
:
1095 return "bag not found";
1098 case KB_BagNotLoaded
:
1099 return "bag not loaded";
1101 return "bag exists";
1102 case KB_InvalidSession
:
1103 return "invalid session";
1109 void service_peer_event_handler(xpc_connection_t connection
, xpc_object_t event
)
1111 xpc_type_t type
= xpc_get_type(event
);
1114 if (type
== XPC_TYPE_ERROR
) {
1115 if (event
== XPC_ERROR_CONNECTION_INVALID
) {
1118 assert(type
== XPC_TYPE_DICTIONARY
);
1120 int rc
= KB_GeneralError
;
1121 uint64_t request
= 0;
1122 const uint8_t * secret
= NULL
, * new_secret
= NULL
;
1123 size_t secret_len
= 0, new_secret_len
= 0, data_len
= 0;
1124 service_context_t
* context
= NULL
;
1125 bool free_context
= false;
1127 const char *entitlement
;
1129 xpc_object_t reply
= xpc_dictionary_create_reply(event
);
1131 request
= xpc_dictionary_get_uint64(event
, SERVICE_XPC_REQUEST
);
1134 // For SERVICE_KB_{UNLOAD,LOAD} only, allow non-securityd, non-root but
1135 // entitled callers.
1136 if (request
== SERVICE_KB_UNLOAD
|| request
== SERVICE_KB_LOAD_UID
) {
1138 case SERVICE_KB_UNLOAD
:
1139 entitlement
= "com.apple.private.securityd.keybag-unload";
1141 case SERVICE_KB_LOAD_UID
:
1142 entitlement
= "com.apple.private.securityd.keybag-load";
1145 if (!peer_has_entitlement(connection
, entitlement
) && !peer_has_entitlement(connection
, "com.apple.keystore.device")) {
1146 xpc_connection_cancel(connection
);
1150 if (xpc_connection_get_euid(connection
) != 0) {
1151 xpc_connection_cancel(connection
);
1154 if (!check_signature(connection
)) {
1155 xpc_connection_cancel(connection
);
1160 data
= xpc_dictionary_get_data(event
, SERVICE_XPC_CONTEXT
, &data_len
);
1161 require_action(data
|| request
== SERVICE_KB_UNLOAD
|| request
== SERVICE_KB_LOAD_UID
, done
, rc
= KB_GeneralError
);
1163 require(data_len
== sizeof(service_context_t
), done
);
1164 context
= (service_context_t
*)data
;
1166 audit_token_t audit_token
= { 0 };
1167 xpc_connection_get_audit_token(connection
, &audit_token
);
1168 context
= calloc(1, sizeof(service_context_t
));
1169 context
->s_id
= xpc_connection_get_asid(connection
);
1170 context
->s_uid
= xpc_connection_get_euid(connection
);
1171 context
->procToken
= audit_token
;
1172 free_context
= true;
1175 require_action(context
->s_id
!= AU_DEFAUDITSID
, done
, rc
= KB_InvalidSession
);
1176 require_action(context
->s_uid
!= AU_DEFAUDITID
, done
, rc
= KB_InvalidSession
); // we only want to work in actual user sessions.
1179 case SERVICE_KB_CREATE
:
1180 // if (kb_service_has_entitlement(peer, "com.apple.keystore.device")) {
1181 secret
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET
, &secret_len
);
1182 rc
= service_kb_create(context
, secret
, (int)secret_len
);
1185 case SERVICE_KB_LOAD
:
1186 rc
= service_kb_load(context
);
1188 case SERVICE_KB_UNLOAD
:
1189 rc
= service_kb_unload(context
);
1191 case SERVICE_KB_SAVE
:
1192 rc
= service_kb_save(context
);
1194 case SERVICE_KB_UNLOCK
:
1195 secret
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET
, &secret_len
);
1196 rc
= service_kb_unlock(context
, secret
, (int)secret_len
);
1198 case SERVICE_KB_LOCK
:
1199 rc
= service_kb_lock(context
);
1201 case SERVICE_KB_CHANGE_SECRET
:
1202 secret
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET
, &secret_len
);
1203 new_secret
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET_NEW
, &new_secret_len
);
1204 rc
= service_kb_change_secret(context
, secret
, (int)secret_len
, new_secret
, (int)new_secret_len
);
1206 case SERVICE_KB_RESET
:
1207 secret
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET
, &secret_len
);
1208 rc
= service_kb_reset(context
, secret
, (int)secret_len
);
1210 case SERVICE_KB_IS_LOCKED
:
1211 rc
= service_kb_is_locked(context
, reply
);
1213 case SERVICE_STASH_GET_KEY
:
1214 rc
= service_stash_get_key(context
, event
, reply
);
1216 case SERVICE_STASH_SET_KEY
:
1217 rc
= service_stash_set_key(context
, event
, reply
);
1219 case SERVICE_STASH_LOAD_KEY
:
1220 rc
= service_stash_load_key(context
, event
, reply
);
1222 case SERVICE_KB_LOAD_UID
:
1223 uid
= (uid_t
)xpc_dictionary_get_uint64(event
, SERVICE_XPC_UID
);
1224 rc
= service_kb_load_uid(uid
);
1226 case SERVICE_KB_WRAP_KEY
:
1227 rc
= service_kb_wrap_key(context
, event
, reply
);
1229 case SERVICE_KB_UNWRAP_KEY
:
1230 rc
= service_kb_unwrap_key(context
, event
, reply
);
1233 case SERVICE_STASH_BLOB
:
1234 rc
= service_stash_blob(event
, reply
);
1238 LOG("unknown service type");
1244 LOG("selector: %s (%llu), error: %s (%x), sid: %d, suid: %d, pid: %d", sel_to_char(request
), request
, err_to_char(rc
), rc
, context
? context
->s_id
: 0, context
? context
->s_uid
: 0, context
? get_caller_pid(&context
->procToken
) : 0);
1247 os_log(OS_LOG_DEFAULT
, "selector: %s (%llu), error: %s (%x), sid: %d, suid: %d, pid: %d", sel_to_char(request
), request
, err_to_char(rc
), rc
, context
? context
->s_id
: 0, context
? context
->s_uid
: 0, context
? get_caller_pid(&context
->procToken
) : 0);
1250 xpc_dictionary_set_int64(reply
, SERVICE_XPC_RC
, rc
);
1251 xpc_connection_send_message(connection
, reply
);
1259 bool check_signature(xpc_connection_t connection
)
1261 #if !(DEBUG || RC_BUILDIT_YES)
1262 audit_token_t token
;
1264 xpc_connection_get_audit_token(connection
, &token
);
1266 SecTaskRef task
= SecTaskCreateWithAuditToken(NULL
, token
);
1268 os_log(OS_LOG_DEFAULT
, "failed getting SecTaskRef of the client");
1272 uint32_t flags
= SecTaskGetCodeSignStatus(task
);
1273 /* check if valid and platform binary, but not platform path */
1274 if ((flags
& (CS_VALID
| CS_PLATFORM_BINARY
| CS_PLATFORM_PATH
)) != (CS_VALID
| CS_PLATFORM_BINARY
)) {
1275 os_log(OS_LOG_DEFAULT
, "client is not a platform binary: %0x08x", flags
);
1280 CFStringRef signingIdentity
= SecTaskCopySigningIdentifier(task
, NULL
);
1282 if (signingIdentity
== NULL
) {
1283 os_log(OS_LOG_DEFAULT
, "client have no code sign identity");
1287 bool res
= CFEqual(signingIdentity
, CFSTR("com.apple.securityd"));
1288 CFRelease(signingIdentity
);
1291 os_log(OS_LOG_DEFAULT
, "client is not not securityd");
1299 static void register_for_notifications()
1301 __block kern_return_t kr
;
1302 static mach_port_t mp
= MACH_PORT_NULL
;
1304 static dispatch_once_t onceToken
= 0;
1305 dispatch_once(&onceToken
, ^{
1306 kr
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &mp
);
1307 if (kr
== KERN_SUCCESS
) {
1308 dispatch_source_t mach_src
= dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV
, mp
, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0));
1309 dispatch_source_set_event_handler(mach_src
, ^{
1310 mach_msg_return_t mr
;
1311 uint8_t buf
[sizeof(aks_notification_msg_t
) + MAX_TRAILER_SIZE
] = {};
1312 aks_notification_msg_t
* msg
= (aks_notification_msg_t
*)buf
;
1313 mr
= mach_msg((mach_msg_header_t
*)&buf
, MACH_RCV_MSG
, 0, sizeof(buf
), mp
, MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
1314 if (mr
== MACH_MSG_SUCCESS
&& msg
->hdr
.msgh_id
== AKS_NOTIFICATION_MSGID
) {
1316 } else if (mr
== MACH_MSG_SUCCESS
&& msg
->hdr
.msgh_id
== AKS_NOTIFICATION_WRITE_SYSTEM_KEYBAG
) {
1317 os_log(OS_LOG_DEFAULT
, "request to update handle %d", msg
->handle
);
1318 update_keybag_handle(msg
->handle
);
1320 os_log(OS_LOG_DEFAULT
, "mach_msg error: %x", mr
);
1323 dispatch_resume(mach_src
);
1325 os_log(OS_LOG_DEFAULT
, "failed to create notification port");
1330 kr
= aks_register_for_notifications(mp
, AKS_NOTIFICATION_WRITE_SYSTEM_KEYBAG
);
1331 if (kr
== KERN_SUCCESS
) {
1332 os_log(OS_LOG_DEFAULT
, "registered for notifications");
1334 os_log(OS_LOG_DEFAULT
, "failed to register for notifications %d", kr
);
1338 int main(int argc
, const char * argv
[])
1341 if (sandbox_init(SECURITYD_SERVICE_NAME
, SANDBOX_NAMED
, &errorbuf
) != 0) {
1342 os_log(OS_LOG_DEFAULT
, "sandbox_init failed %s", errorbuf
);
1343 sandbox_free_error(errorbuf
);
1349 register_for_notifications();
1351 xpc_connection_t listener
= xpc_connection_create_mach_service(SECURITYD_SERVICE_NAME
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1352 xpc_connection_set_event_handler(listener
, ^(xpc_object_t peer
) {
1353 // It is safe to cast 'peer' to xpc_connection_t assuming
1354 // we have a correct configuration in our launchd.plist.
1355 xpc_connection_set_event_handler(peer
, ^(xpc_object_t event
) {
1356 vproc_transaction_t transaction
= vproc_transaction_begin(NULL
);
1357 service_peer_event_handler(peer
, event
);
1358 vproc_transaction_end(NULL
, transaction
);
1360 xpc_connection_resume(peer
);
1362 xpc_connection_resume(listener
);