1 /* Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. */
3 #include "securityd_service.h"
4 #include "securityd_service_client.h"
9 #include <xpc/private.h>
10 #include <dispatch/dispatch.h>
11 #include <sys/types.h>
13 #include <sys/codesign.h>
20 #include <uuid/uuid.h>
21 #include <bsm/libbsm.h>
23 #include <AssertMacros.h>
24 #include <Security/Security.h>
25 #include <Security/SecTask.h>
26 #include <Security/SecTaskPriv.h>
27 #include <Security/SecKeychainPriv.h>
28 #include <Security/SecInternalReleasePriv.h>
29 #include <MobileKeyBag/MobileKeyBag.h>
30 #include <corecrypto/ccsha2.h>
31 #include <corecrypto/cchmac.h>
33 #include <IOKit/IOKitLib.h>
34 #include <Kernel/IOKit/crypto/AppleFDEKeyStoreDefs.h>
36 #define LOG(...) os_log_debug(OS_LOG_DEFAULT, ##__VA_ARGS__);
38 static bool check_signature(xpc_connection_t connection
);
40 static pid_t
get_caller_pid(audit_token_t
* token
)
44 audit_token_to_au32(*token
, NULL
, NULL
, NULL
, NULL
, NULL
, &pid
, NULL
, NULL
);
49 // exported from libaks.a
50 kern_return_t
aks_register_for_notifications(mach_port_t server_port
, uintptr_t message_id
);
51 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
);
53 const char * kb_home_path
= "Library/Keychains";
54 const char * kb_user_bag
= "user.kb";
55 const char * kb_stash_bag
= "stash.kb";
57 #define HEXBUF_LEN 2048
64 } service_user_record_t
;
74 io_registry_entry_t service
;
78 service
= IOServiceGetMatchingService(kIOMasterPortDefault
, IOServiceMatching(kAppleFDEKeyStoreServiceName
));
79 if (service
== IO_OBJECT_NULL
)
80 return IO_OBJECT_NULL
;
82 kr
= IOServiceOpen(service
, mach_task_self(), 0, &conn
);
83 if (kr
!= KERN_SUCCESS
)
84 return IO_OBJECT_NULL
;
86 kr
= IOConnectCallMethod(conn
, kAppleFDEKeyStoreUserClientOpen
, NULL
, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
87 if (kr
!= KERN_SUCCESS
) {
89 return IO_OBJECT_NULL
;
96 closeiodev(io_connect_t conn
)
99 kr
= IOConnectCallMethod(conn
, kAppleFDEKeyStoreUserClientClose
, NULL
, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
100 if (kr
!= KERN_SUCCESS
)
102 IOServiceClose(conn
);
105 static dispatch_queue_t
106 _kb_service_get_dispatch_queue()
108 static dispatch_once_t onceToken
= 0;
109 static dispatch_queue_t connection_queue
= NULL
;
111 dispatch_once(&onceToken
, ^{
112 connection_queue
= dispatch_queue_create("kb-service-queue", DISPATCH_QUEUE_SERIAL
);
115 return connection_queue
;
118 static service_user_record_t
* get_user_record(uid_t uid
)
120 service_user_record_t
* ur
= NULL
;
122 if ((bufsize
= sysconf(_SC_GETPW_R_SIZE_MAX
)) == -1) {
125 char *buf
= calloc(1, (size_t)bufsize
);
126 struct passwd pwbuf
, *pw
= NULL
;
128 if (((rc
= getpwuid_r(uid
, &pwbuf
, buf
, bufsize
, &pw
)) == 0) && pw
!= NULL
) {
129 ur
= calloc(1u, sizeof(service_user_record_t
));
131 ur
->uid
= pw
->pw_uid
;
132 ur
->gid
= pw
->pw_gid
;
133 ur
->home
= strdup(pw
->pw_dir
);
134 ur
->name
= strdup(pw
->pw_name
);
136 os_log(OS_LOG_DEFAULT
, "failed (%d) to lookup user record for uid: %d", rc
, uid
);
144 static void free_user_record(service_user_record_t
* ur
)
157 static const char * get_host_uuid()
159 static uuid_string_t hostuuid
= {};
160 static dispatch_once_t onceToken
;
161 dispatch_once(&onceToken
, ^{
162 struct timespec timeout
= {30, 0};
164 if (gethostuuid(uuid
, &timeout
) == 0) {
165 uuid_unparse(uuid
, hostuuid
);
167 os_log(OS_LOG_DEFAULT
, "failed to get host uuid");
176 compute_kcv(uint8_t * key
, size_t key_len
)
178 uint8_t hmac
[CCSHA256_OUTPUT_SIZE
] = { 0 };
179 uint8_t kcv_data
[] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
180 cchmac(ccsha256_di(), key_len
, key
, sizeof(kcv_data
), kcv_data
, hmac
);
181 return (uint64_t)(*(uint64_t *)hmac
);
185 _kb_copy_bag_filename(service_user_record_t
* ur
, kb_bag_type_t type
)
187 char * bag_file
= NULL
;
188 const char * name
= NULL
;
192 case kb_bag_type_user
:
195 case kb_bag_type_stash
:
202 bag_file
= calloc(1u, PATH_MAX
);
203 require(bag_file
, done
);
205 snprintf(bag_file
, PATH_MAX
, "%s/%s/%s/%s", ur
->home
, kb_home_path
, get_host_uuid(), name
);
212 _kb_verify_create_path(service_user_record_t
* ur
)
214 bool created
= false;
215 struct stat st_info
= {};
216 char new_path
[PATH_MAX
] = {};
217 char kb_path
[PATH_MAX
] = {};
218 snprintf(kb_path
, sizeof(kb_path
), "%s/%s/%s", ur
->home
, kb_home_path
, get_host_uuid());
219 if (lstat(kb_path
, &st_info
) == 0) {
220 if (S_ISDIR(st_info
.st_mode
)) {
223 os_log(OS_LOG_DEFAULT
, "invalid directory at '%{public}s' moving aside", kb_path
);
224 snprintf(new_path
, sizeof(new_path
), "%s-invalid", kb_path
);
226 if (rename(kb_path
, new_path
) != 0) {
227 os_log(OS_LOG_DEFAULT
, "failed to rename file: %{public}s %{darwin.errno}d", kb_path
, errno
);
233 errno_t err
= mkpath_np(kb_path
, 0700);
234 require_action(err
== 0 || err
== EEXIST
, done
, os_log(OS_LOG_DEFAULT
, "could not create path: %{public}s %{darwin.errno}d", kb_path
, err
));
240 os_log(OS_LOG_DEFAULT
, "_kb_verify_create_path failed %{public}s", kb_path
);
246 _set_thread_credentials(service_user_record_t
* ur
)
248 int rc
= pthread_setugid_np(ur
->uid
, ur
->gid
);
249 if (rc
) { os_log(OS_LOG_DEFAULT
, "failed to set thread credential: %{darwin.errno}d", errno
); }
251 rc
= initgroups(ur
->name
, ur
->gid
);
252 if (rc
) { os_log(OS_LOG_DEFAULT
, "failed to initgroups: %i", rc
); }
256 _clear_thread_credentials()
258 int rc
= pthread_setugid_np(KAUTH_UID_NONE
, KAUTH_GID_NONE
);
259 if (rc
) { os_log(OS_LOG_DEFAULT
, "failed to reset thread credential: %{darwin.errno}d", errno
); }
263 _kb_bag_exists(service_user_record_t
* ur
, const char * bag_file
)
266 struct stat st_info
= {};
267 char new_file
[PATH_MAX
] = {};
271 _set_thread_credentials(ur
);
272 if (lstat(bag_file
, &st_info
) == 0) {
273 if (S_ISREG(st_info
.st_mode
)) {
276 os_log(OS_LOG_DEFAULT
, "invalid file at '%{public}s' moving aside", bag_file
);
277 snprintf(new_file
, sizeof(new_file
), "%s-invalid", bag_file
);
279 if (rename(bag_file
, new_file
) != 0) {
280 os_log(OS_LOG_DEFAULT
, "failed to rename file: %{public}s %{darwin.errno}d", bag_file
, errno
);
286 _clear_thread_credentials();
291 _kb_save_bag_to_disk(service_user_record_t
* ur
, const char * bag_file
, void * data
, size_t length
, uint64_t * kcv
)
294 char tmp_bag
[PATH_MAX
];
297 require(bag_file
, done
);
299 _set_thread_credentials(ur
);
300 require(_kb_verify_create_path(ur
), done
);
302 require_action(snprintf(tmp_bag
, sizeof(tmp_bag
), "%s.tmp", bag_file
) < sizeof(tmp_bag
), done
, os_log(OS_LOG_DEFAULT
, "path too large"));
304 fd
= open(tmp_bag
, O_CREAT
| O_TRUNC
| O_WRONLY
| O_NOFOLLOW
, 0600);
305 require_action(fd
!= -1, done
, os_log(OS_LOG_DEFAULT
, "could not create file: %{public}s %{darwin.errno}d", tmp_bag
, errno
));
306 require_action(write(fd
, data
, length
) == length
, done
, os_log(OS_LOG_DEFAULT
, "failed to write keybag to disk %s %{darwin.errno}d", tmp_bag
, errno
));
308 /* try atomic swap (will fail if destination doesn't exist); if that fails, try regular rename */
309 if (renamex_np(tmp_bag
, bag_file
, RENAME_SWAP
) != 0) {
310 os_log(OS_LOG_DEFAULT
, "Warning: atomic swap failed, error= %{darwin.errno}d", errno
);
311 require_noerr_action(rename(tmp_bag
, bag_file
), done
, os_log(OS_LOG_DEFAULT
, "could not save keybag file, error= %{darwin.errno}d", errno
));
313 (void)unlink(tmp_bag
);
315 *kcv
= compute_kcv(data
, length
);
319 if (fd
!= -1) { close(fd
); }
320 _clear_thread_credentials();
325 _kb_load_bag_from_disk(service_user_record_t
* ur
, const char * bag_file
, uint8_t ** data
, size_t * length
, uint64_t * kcv
)
329 uint8_t * buf
= NULL
;
331 struct stat st_info
= {};
333 require(bag_file
, done
);
335 _set_thread_credentials(ur
);
336 require(_kb_verify_create_path(ur
), done
);
337 require_action_quiet(lstat(bag_file
, &st_info
) == 0, done
, os_log(OS_LOG_DEFAULT
, "failed to stat file: %{public}s %{darwin.errno}d", bag_file
, errno
));
338 require_action(S_ISREG(st_info
.st_mode
), done
, os_log(OS_LOG_DEFAULT
, "failed to load, not a file: %{public}s", bag_file
));
339 buf_size
= (size_t)st_info
.st_size
;
341 fd
= open(bag_file
, O_RDONLY
| O_NOFOLLOW
);
342 require_action(fd
!= -1, done
, os_log(OS_LOG_DEFAULT
, "could not open file: %{public}s %{darwin.errno}d", bag_file
, errno
));
344 buf
= (uint8_t *)calloc(1u, buf_size
);
345 require(buf
!= NULL
, done
);
346 require(read(fd
, buf
, buf_size
) == buf_size
, done
);
348 *kcv
= compute_kcv(buf
, buf_size
);
355 if (fd
!= -1) { close(fd
); }
356 if (buf
) { free(buf
); }
357 _clear_thread_credentials();
362 _kb_invalidate_bag(service_user_record_t
*ur
, const char * bag_file
, uint64_t * kcv
)
369 if (_kb_load_bag_from_disk(ur
, bag_file
, &buf
, &buf_size
, kcv
)) {
370 require_action(buf
&& buf_size
<= INT_MAX
, out
, os_log(OS_LOG_DEFAULT
, "failed to read: %{public}s", bag_file
));
371 require_noerr_action(aks_invalidate_bag(buf
, (int)buf_size
), out
, os_log(OS_LOG_DEFAULT
, "failed to invalidate file: %{public}s", bag_file
));
373 os_log(OS_LOG_DEFAULT
, "failed to read file: %{public}s", bag_file
);
381 _kb_rename_bag_on_disk(service_user_record_t
* ur
, const char * bag_file
, uint64_t * kcv
)
383 char new_file
[PATH_MAX
] = {};
385 _set_thread_credentials(ur
);
386 snprintf(new_file
, sizeof(new_file
), "%s-invalid", bag_file
);
388 rename(bag_file
, new_file
);
389 _kb_invalidate_bag(ur
, new_file
, kcv
);
390 _clear_thread_credentials();
395 _kb_delete_bag_on_disk(service_user_record_t
* ur
, const char * bag_file
, uint64_t * kcv
)
398 _set_thread_credentials(ur
);
399 _kb_invalidate_bag(ur
, bag_file
, kcv
);
401 _clear_thread_credentials();
405 static int service_kb_load(service_context_t
*context
);
406 static int service_kb_load_uid(uid_t s_uid
, uint64_t * kcv
);
409 _service_kb_set_system(keybag_handle_t handle
, keybag_handle_t special_handle
)
411 //Use reserved root handle for root sessions, since 0 clashes with device_keybag_handle in AKS
412 return aks_set_system(handle
, (special_handle
== 0) ? AKS_MACOS_ROOT_HANDLE
: special_handle
);
416 _service_kb_get_system(keybag_handle_t special_handle
, keybag_handle_t
* handle_out
)
418 //Use reserved root handle for root sessions, since 0 clashes with device_keybag_handle in AKS
419 return aks_get_system((special_handle
== 0) ? AKS_MACOS_ROOT_HANDLE
: special_handle
, handle_out
);
423 _kb_get_session_handle(service_context_t
* context
, keybag_handle_t
* handle_out
)
425 int rc
= KB_BagNotLoaded
;
426 require_noerr_quiet(_service_kb_get_system(context
->s_uid
, handle_out
), done
);
431 if (rc
== KB_BagNotLoaded
) {
432 if (service_kb_load(context
) == KB_Success
) {
433 if (_service_kb_get_system(context
->s_uid
, handle_out
) == kAKSReturnSuccess
) {
441 static void update_keybag_handle(keybag_handle_t handle
)
443 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
444 uid_t uid
= (handle
== (-AKS_MACOS_ROOT_HANDLE
)) ? 0 : abs(handle
);
445 uint8_t * buf
= NULL
;
447 service_user_record_t
* ur
= NULL
;
448 char * bag_file
= NULL
;
451 require_noerr(aks_save_bag(handle
, (void**)&buf
, (int*)&buf_size
), done
);
452 require(ur
= get_user_record(uid
), done
);
453 require(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
);
454 require(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
, &kcv
), done
);
456 os_log(OS_LOG_DEFAULT
, "successfully updated handle %d, save keybag kcv: 0x%0llx", handle
, kcv
);
460 if (ur
) free_user_record(ur
);
461 if (bag_file
) free(bag_file
);
466 _kb_get_options_for_uid(uid_t uid
, CFMutableDictionaryRef
*options_out
)
468 int result
= KB_GeneralError
;
469 CFMutableDictionaryRef options
= NULL
;
470 CFNumberRef cf_uid
= NULL
;
472 require(options_out
, out
);
474 require(options
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
), out
);
475 require(cf_uid
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberIntType
, &uid
), out
);
476 CFDictionaryAddValue(options
, kKeyBagDeviceHandle
, cf_uid
);
478 *options_out
= options
;
483 if (options
) { CFRelease(options
); }
484 if (cf_uid
) { CFRelease(cf_uid
); }
490 _kb_set_properties(service_context_t
* context
, const void * secret
, int secret_len
)
492 int result
= KB_GeneralError
;
493 CFMutableDictionaryRef options
= NULL
;
494 CFDataRef passcode
= NULL
;
496 require_noerr(_kb_get_options_for_uid(context
->s_uid
, &options
), done
);
498 /* set user uuid, if not already set */
499 passcode
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, secret
, secret_len
, kCFAllocatorNull
);
500 if (MKBKeyBagSetUserUUID(options
, passcode
)) {
501 os_log(OS_LOG_DEFAULT
, "set user uuid failed");
504 #ifdef MKB_SUPPORTS_BIND_KEK
505 if (MKBKeyBagBindKEK(options
, passcode
)) {
506 os_log(OS_LOG_DEFAULT
, "KEK bind failed");
509 os_log(OS_LOG_DEFAULT
, "Not bindinig KEK, update SDK");
514 if (options
) { CFRelease(options
); }
515 if (passcode
) { CFRelease(passcode
); }
520 service_kb_create(service_context_t
* context
, const void * secret
, int secret_len
)
522 __block
int rc
= KB_GeneralError
;
524 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
525 uint8_t * buf
= NULL
;
527 keybag_handle_t private_handle
= bad_keybag_handle
, session_handle
= bad_keybag_handle
;
528 service_user_record_t
* ur
= get_user_record(context
->s_uid
);
529 char * bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_user
);
531 require(bag_file
, done
);
533 // check for the existance of the bagfile
534 require_action(!_kb_bag_exists(ur
, bag_file
), done
, rc
= KB_BagExists
);
536 require_noerr(rc
= aks_create_bag(secret
, secret_len
, kAppleKeyStoreDeviceBag
, &private_handle
), done
);
537 require_noerr(rc
= aks_save_bag(private_handle
, (void**)&buf
, (int*)&buf_size
), done
);
538 require_action(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
, &context
->kcv
), done
, rc
= KB_BagError
);
539 require_noerr(rc
= _service_kb_set_system(private_handle
, context
->s_uid
), done
);
540 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
542 if (secret
&& rc
== KB_Success
) {
543 aks_unlock_bag(session_handle
, secret
, secret_len
);
546 if (rc
== KB_Success
) {
547 _kb_set_properties(context
, secret
, secret_len
);
551 if (private_handle
!= bad_keybag_handle
) {
552 aks_unload_bag(private_handle
);
555 if (bag_file
) { free(bag_file
); }
556 if (ur
) free_user_record(ur
);
562 /* Load s_uid's keybag, unless already loaded */
564 _service_kb_load_uid(uid_t s_uid
, uint64_t * kcv
)
566 __block
int rc
= KB_GeneralError
;
568 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
569 uint8_t * buf
= NULL
;
571 keybag_handle_t private_handle
= bad_keybag_handle
, session_handle
= bad_keybag_handle
;
572 service_user_record_t
* ur
= NULL
;
573 char * bag_file
= NULL
;
576 rc
= _service_kb_get_system(s_uid
, &session_handle
);
577 if (rc
== kAKSReturnNotFound
) {
578 require_action(ur
= get_user_record(s_uid
), done
, rc
= KB_GeneralError
; _stage
= 1);
579 require_action(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
, rc
= KB_GeneralError
; _stage
= 2);
580 require_action_quiet(_kb_load_bag_from_disk(ur
, bag_file
, &buf
, &buf_size
, kcv
), done
, rc
= KB_BagNotFound
; _stage
= 3);
581 rc
= aks_load_bag(buf
, (int)buf_size
, &private_handle
);
583 case kAKSReturnBadDeviceKey
:
584 case kAKSReturnBadSignature
:
585 case kAKSReturnDecodeError
:
586 case kAKSReturnPolicyInvalid
:
587 os_log(OS_LOG_DEFAULT
, "bag load failed 0x%x for uid (%i), discarding", rc
, s_uid
);
588 _kb_rename_bag_on_disk(ur
, bag_file
, kcv
);
591 case kAKSReturnSuccess
:
595 os_log(OS_LOG_DEFAULT
, "bag load failed 0x%x for uid (%i)", rc
, s_uid
);
598 require_noerr_action(rc
, done
, _stage
= 4);
599 require_noerr_action(rc
= _service_kb_set_system(private_handle
, s_uid
), done
, _stage
= 5);
601 require(rc
== KB_Success
, done
);
604 if (private_handle
!= bad_keybag_handle
) {
605 aks_unload_bag(private_handle
);
607 // this function should never fail unless bootstrapping the user for the first time, or rare conditions from aks_load_bag
608 if (rc
!= KB_Success
) {
609 os_log(OS_LOG_DEFAULT
, "%d: error %d loading keybag for uid (%i) at path: %{public}s", _stage
, rc
, s_uid
, bag_file
);
612 if (ur
) free_user_record(ur
);
613 if (bag_file
) free(bag_file
);
620 service_kb_load_uid(uid_t s_uid
, uint64_t * kcv
)
622 return _service_kb_load_uid(s_uid
, kcv
);
626 service_kb_load(service_context_t
* context
)
628 return _service_kb_load_uid(context
->s_uid
, &context
->kcv
);
632 service_kb_unload(service_context_t
*context
)
634 __block
int rc
= KB_GeneralError
;
636 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
637 keybag_handle_t session_handle
= bad_keybag_handle
;
639 rc
= _service_kb_get_system(context
->s_uid
, &session_handle
);
640 if (rc
== kAKSReturnNotFound
) {
641 // No session bag, nothing to do
644 } else if (rc
!= kAKSReturnSuccess
) {
645 os_log(OS_LOG_DEFAULT
, "error locating session keybag for uid (%i) in session (%i)", context
->s_uid
, context
->s_id
);
650 rc
= aks_unload_bag(session_handle
);
651 if (rc
!= kAKSReturnSuccess
) {
652 os_log(OS_LOG_DEFAULT
, "error unloading keybag for uid (%i) in session (%i)", context
->s_uid
, context
->s_id
);
655 os_log(OS_LOG_DEFAULT
, "successfully unloaded keybag (%ld) for uid (%i) in session (%i)", (long)session_handle
, context
->s_uid
, context
->s_id
);
663 service_kb_save(service_context_t
* context
)
665 __block
int rc
= KB_GeneralError
;
666 keybag_handle_t session_handle
;
667 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
669 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
670 uint8_t * buf
= NULL
;
672 service_user_record_t
* ur
= NULL
;
673 char * bag_file
= NULL
;
675 require_noerr(rc
= aks_save_bag(session_handle
, (void**)&buf
, (int*)&buf_size
), done
);
676 require_action(ur
= get_user_record(context
->s_uid
), done
, rc
= KB_GeneralError
);
677 require_action(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
, rc
= KB_GeneralError
);
678 require_action(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
, &context
->kcv
), done
, rc
= KB_BagError
);
684 if (ur
) free_user_record(ur
);
685 if (bag_file
) free(bag_file
);
694 service_kb_unlock(service_context_t
* context
, const void * secret
, int secret_len
)
696 int rc
= KB_GeneralError
;
697 keybag_handle_t session_handle
;
698 CFDataRef passcode
= NULL
;
699 CFMutableDictionaryRef options
= NULL
;
701 require_noerr(_kb_get_options_for_uid(context
->s_uid
, &options
), done
);
703 /* technically, session_handle is not needed. Call this to handle lazy keybag loading */
704 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
706 require(passcode
= CFDataCreateWithBytesNoCopy(NULL
, secret
, secret_len
, kCFAllocatorNull
), done
);
708 rc
= MKBUnlockDevice(passcode
, options
);
709 os_log_info(OS_LOG_DEFAULT
, "MKBUnlockDevice result: (%ld), caller pid: %d", (long)rc
, get_caller_pid(&context
->procToken
));
712 if (options
) { CFRelease(options
); }
713 if (passcode
) { CFRelease(passcode
); }
718 service_kb_lock(service_context_t
* context
)
720 // this call has been disabled
725 service_kb_change_secret(service_context_t
* context
, const void * secret
, int secret_len
, const void * new_secret
, int new_secret_len
)
727 __block
int rc
= KB_GeneralError
;
728 keybag_handle_t session_handle
;
729 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
731 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
732 uint8_t * buf
= NULL
;
734 service_user_record_t
* ur
= NULL
;
735 char * bag_file
= NULL
;
737 require_noerr(rc
= aks_change_secret(session_handle
, secret
, secret_len
, new_secret
, new_secret_len
, generation_noop
, NULL
), done
);
738 require_noerr(rc
= aks_save_bag(session_handle
, (void**)&buf
, (int*)&buf_size
), done
);
739 require_action(ur
= get_user_record(context
->s_uid
), done
, rc
= KB_GeneralError
);
740 require_action(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
, rc
= KB_GeneralError
);
741 require_action(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
, &context
->kcv
), done
, rc
= KB_BagError
);
747 if (ur
) free_user_record(ur
);
748 if (bag_file
) free(bag_file
);
757 service_kb_reset(service_context_t
* context
, const void * secret
, int secret_len
)
759 __block
int rc
= KB_GeneralError
;
760 service_user_record_t
* ur
= NULL
;
761 char * bag_file
= NULL
;
763 require_action(ur
= get_user_record(context
->s_uid
), done
, rc
= KB_GeneralError
);
764 require_action(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
, rc
= KB_GeneralError
);
766 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
767 uint8_t * buf
= NULL
;
769 keybag_handle_t private_handle
= bad_keybag_handle
, session_handle
= bad_keybag_handle
;
771 os_log(OS_LOG_DEFAULT
, "resetting keybag for uid (%i) in session (%i)", context
->s_uid
, context
->s_id
);
772 _kb_rename_bag_on_disk(ur
, bag_file
, &context
->kcv
);
774 require_noerr(rc
= aks_create_bag(secret
, secret_len
, kAppleKeyStoreDeviceBag
, &private_handle
), done
);
775 require_noerr(rc
= aks_save_bag(private_handle
, (void**)&buf
, (int*)&buf_size
), done
);
776 require_action(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
, &context
->kcv
), done
, rc
= KB_BagError
);
777 require_noerr(rc
= _service_kb_set_system(private_handle
, context
->s_uid
), done
);
778 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
780 if (secret
&& rc
== KB_Success
) {
781 aks_unlock_bag(session_handle
, secret
, secret_len
);
784 if (rc
== KB_Success
) {
785 _kb_set_properties(context
, secret
, secret_len
);
789 if (private_handle
!= bad_keybag_handle
) {
790 aks_unload_bag(private_handle
);
797 if (ur
) free_user_record(ur
);
798 if (bag_file
) free(bag_file
);
803 service_kb_is_locked(service_context_t
* context
, xpc_object_t reply
)
805 int rc
= KB_GeneralError
;
806 keybag_state_t state
;
807 keybag_handle_t session_handle
;
808 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
810 require_noerr(rc
= aks_get_lock_state(session_handle
, &state
), done
);
812 xpc_dictionary_set_bool(reply
, SERVICE_XPC_LOCKED
, state
& keybag_state_locked
);
813 xpc_dictionary_set_bool(reply
, SERVICE_XPC_NO_PIN
, state
& keybag_state_no_pin
);
820 service_kb_wrap_key(service_context_t
*context
, xpc_object_t event
, xpc_object_t reply
)
822 int rc
= KB_GeneralError
;
826 keyclass_t key_class
;
827 keybag_handle_t session_handle
;
828 void *wrapped_key
= NULL
;
829 int wrapped_key_size
;
830 keyclass_t wrapped_key_class
;
832 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
834 key
= xpc_dictionary_get_data(event
, SERVICE_XPC_KEY
, &sz
);
835 require_action(key
!= NULL
, done
, rc
= KB_GeneralError
);
836 require_action(sz
<= APPLE_KEYSTORE_MAX_KEY_LEN
, done
, rc
= KB_GeneralError
);
838 key_class
= (keyclass_t
)xpc_dictionary_get_int64(event
, SERVICE_XPC_KEYCLASS
);
840 wrapped_key_size
= APPLE_KEYSTORE_MAX_ASYM_WRAPPED_KEY_LEN
;
841 wrapped_key
= calloc(1, wrapped_key_size
);
843 rc
= aks_wrap_key(key
, key_size
, key_class
, session_handle
, wrapped_key
, &wrapped_key_size
, &wrapped_key_class
);
844 if (rc
== KB_Success
) {
845 xpc_dictionary_set_data(reply
, SERVICE_XPC_WRAPPED_KEY
, wrapped_key
, wrapped_key_size
);
846 xpc_dictionary_set_int64(reply
, SERVICE_XPC_KEYCLASS
, wrapped_key_class
);
855 service_kb_unwrap_key(service_context_t
*context
, xpc_object_t event
, xpc_object_t reply
)
857 int rc
= KB_GeneralError
;
859 const void *wrapped_key
;
860 int wrapped_key_size
;
861 keyclass_t wrapped_key_class
;
862 keybag_handle_t session_handle
;
866 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
868 wrapped_key
= xpc_dictionary_get_data(event
, SERVICE_XPC_WRAPPED_KEY
, &sz
);
869 require_action(wrapped_key
!= NULL
, done
, rc
= KB_GeneralError
);
870 require_action(sz
<= APPLE_KEYSTORE_MAX_ASYM_WRAPPED_KEY_LEN
, done
, rc
= KB_GeneralError
);
871 wrapped_key_size
= (int)sz
;
872 wrapped_key_class
= (keyclass_t
)xpc_dictionary_get_int64(event
, SERVICE_XPC_KEYCLASS
);
874 key_size
= APPLE_KEYSTORE_MAX_KEY_LEN
;
875 key
= calloc(1, key_size
);
877 rc
= aks_unwrap_key(wrapped_key
, wrapped_key_size
, wrapped_key_class
, session_handle
, key
, &key_size
);
878 if (rc
== KB_Success
) {
879 xpc_dictionary_set_data(reply
, SERVICE_XPC_KEY
, key
, key_size
);
888 service_kb_stash_create(service_context_t
* context
, const void * key
, unsigned key_size
)
890 int rc
= KB_GeneralError
;
891 char * bag_file
= NULL
;
892 keybag_handle_t session_handle
;
893 service_user_record_t
* ur
= NULL
;
894 void * stashbag
= NULL
;
895 int stashbag_size
= 0;
896 __block
bool saved
= false;
899 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
900 require_action(ur
= get_user_record(context
->s_uid
), done
, rc
= KB_GeneralError
);
901 require_noerr(rc
= aks_stash_escrow(session_handle
, true, key
, key_size
, NULL
, 0, (void**)&stashbag
, &stashbag_size
), done
);
902 require_action(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_stash
), done
, rc
= KB_GeneralError
);
904 // sync writing the bag to disk
905 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
906 saved
= _kb_save_bag_to_disk(ur
, bag_file
, stashbag
, stashbag_size
, &context
->kcv
);
908 require_action(saved
, done
, rc
= KB_BagError
);
912 if (stashbag
) { free(stashbag
); }
913 if (bag_file
) { free(bag_file
); }
914 if (ur
) free_user_record(ur
);
919 service_kb_stash_load(service_context_t
* context
, const void * key
, unsigned key_size
, bool nondestructive
)
921 __block
int rc
= KB_GeneralError
;
922 char * bag_file
= NULL
;
923 keybag_handle_t session_handle
;
924 service_user_record_t
* ur
= NULL
;
925 __block
uint8_t * stashbag
= NULL
;
926 __block
size_t stashbag_size
= 0;
929 require_noerr(rc
= _kb_get_session_handle(context
, &session_handle
), done
);
930 require_action(ur
= get_user_record(context
->s_uid
), done
, rc
= KB_GeneralError
);
931 require_action(bag_file
= _kb_copy_bag_filename(ur
, kb_bag_type_stash
), done
, rc
= KB_GeneralError
);
933 // sync loading the bag from disk
934 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
935 if (!_kb_load_bag_from_disk(ur
, bag_file
, &stashbag
, &stashbag_size
, &context
->kcv
)) {
939 require_noerr(rc
, done
);
941 require_noerr(rc
= aks_stash_escrow(session_handle
, false, key
, key_size
, stashbag
, (int)stashbag_size
, NULL
, NULL
), done
);
945 if (stashbag
) { free(stashbag
); }
946 if ((bag_file
) && (!nondestructive
)) {
947 _kb_delete_bag_on_disk(ur
, bag_file
, &context
->kcv
);
950 if (ur
) free_user_record(ur
);
955 // Get the keychain master key from the AppleFDEKeyStore.
956 // Note that this is a one-time call - the master key is
957 // removed from the keystore after it is returned.
958 // Requires the entitlement: com.apple.private.securityd.keychain
960 OSStatus
service_stash_get_key(service_context_t
* context
, xpc_object_t event
, xpc_object_t reply
)
962 getStashKey_InStruct_t inStruct
;
963 getStashKey_OutStruct_t outStruct
;
964 size_t outSize
= sizeof(outStruct
);
965 kern_return_t kr
= KERN_INVALID_ARGUMENT
;
967 io_connect_t conn
= openiodev();
969 inStruct
.type
= kAppleFDEKeyStoreStash_master
;
971 kr
= IOConnectCallMethod(conn
, kAppleFDEKeyStore_getStashKey
,
973 &inStruct
, sizeof(inStruct
),
975 &outStruct
, &outSize
);
977 if (kr
== KERN_SUCCESS
) {
978 xpc_dictionary_set_data(reply
, SERVICE_XPC_KEY
, outStruct
.outBuf
.key
.key
, outStruct
.outBuf
.key
.keysize
);
979 service_kb_stash_load(context
, outStruct
.outBuf
.key
.key
, outStruct
.outBuf
.key
.keysize
, false);
981 os_log(OS_LOG_DEFAULT
, "failed to get stash key: %d", (int)kr
);
992 // Stash the keychain master key in the AppleFDEKeyStore and
993 // flag it as the keychain master key to be added to the
994 // reboot NVRAM blob.
995 // This requires two calls to the AKS: the first to store the
996 // key and get its uuid. The second uses the uuid to flag the
997 // key for blob inclusion.
999 OSStatus
service_stash_set_key(service_context_t
* context
, xpc_object_t event
, xpc_object_t reply
)
1001 kern_return_t kr
= KERN_INVALID_ARGUMENT
;
1002 io_connect_t conn
= IO_OBJECT_NULL
;
1003 size_t keydata_len
= 0;
1006 keybag_state_t state
;
1007 keybag_handle_t session_handle
;
1008 require_noerr(_kb_get_session_handle(context
, &session_handle
), done
);
1009 require_noerr(aks_get_lock_state(session_handle
, &state
), done
);
1010 require_action(!(state
& keybag_lock_locked
), done
, kr
= CSSMERR_CSP_OS_ACCESS_DENIED
; LOG("stash failed keybag locked"));
1013 require(conn
, done
);
1015 // Store the key in the keystore and get its uuid
1016 setKeyGetUUID_InStruct_t inStruct1
;
1017 uuid_OutStruct_t outStruct1
;
1020 const uint8_t *keydata
= xpc_dictionary_get_data(event
, SERVICE_XPC_KEY
, &keydata_len
);
1021 require(keydata
, done
);
1022 require(keydata_len
<= MAX_KEY_SIZE
, done
);
1024 _Static_assert(sizeof(inStruct1
.inKey
.key
.key
) == MAX_KEY_SIZE
, "unexpected aks raw key size");
1025 memcpy(&inStruct1
.inKey
.key
.key
, keydata
, keydata_len
);
1026 inStruct1
.inKey
.key
.keysize
= (cryptosize_t
) keydata_len
;
1027 len
= sizeof(outStruct1
);
1028 kr
= IOConnectCallMethod(conn
, kAppleFDEKeyStore_setKeyGetUUID
,
1030 &inStruct1
, sizeof(inStruct1
),
1033 require(kr
== KERN_SUCCESS
, done
);
1035 // Now using the uuid stash it as the master key
1036 setStashKey_InStruct_t inStruct2
;
1037 _Static_assert(sizeof(outStruct1
.uuid
) == sizeof(inStruct2
.uuid
), "invalid uuid size(s)");
1038 memcpy(&inStruct2
.uuid
, &outStruct1
.uuid
, sizeof(outStruct1
.uuid
));
1039 inStruct2
.type
= kAppleFDEKeyStoreStash_master
;
1041 kr
= IOConnectCallMethod(conn
, kAppleFDEKeyStore_setStashKey
,
1043 &inStruct2
, sizeof(inStruct2
),
1047 if (kr
== KERN_SUCCESS
) {
1048 service_kb_stash_create(context
, keydata
, (unsigned)keydata_len
);
1051 os_log(OS_LOG_DEFAULT
, "set stashkey %d", (int)kr
);
1060 // Load the master stash key
1062 OSStatus
service_stash_load_key(service_context_t
* context
, xpc_object_t event
, xpc_object_t reply
)
1064 kern_return_t kr
= KERN_SUCCESS
;
1065 size_t keydata_len
= 0;
1067 const uint8_t *keydata
= xpc_dictionary_get_data(event
, SERVICE_XPC_KEY
, &keydata_len
);
1068 require(keydata
, done
);
1070 kr
= service_kb_stash_load(context
, keydata
, (cryptosize_t
) keydata_len
, true);
1077 // Signal the AppleFDEKeyStore to take the tagged FDE key
1078 // and keychain master key, stash them in an encrypted
1079 // blob structure and write the blob to NVRAM. The random
1080 // encryption key is written to the SMC.
1083 OSStatus
service_stash_blob(xpc_object_t event
, xpc_object_t reply
)
1085 kern_return_t kr
= KERN_INVALID_ARGUMENT
;
1087 io_connect_t conn
= openiodev();
1088 require(conn
, done
);
1090 kr
= IOConnectCallMethod(conn
, kAppleFDEKeyStore_commitStash
,
1103 bool peer_has_entitlement(xpc_connection_t peer
, const char * entitlement
)
1105 bool entitled
= false;
1107 xpc_object_t value
= xpc_connection_copy_entitlement_value(peer
, entitlement
);
1108 if (value
&& (xpc_get_type(value
) == XPC_TYPE_BOOL
)) {
1109 entitled
= xpc_bool_get_value(value
);
1112 if (value
) xpc_release(value
);
1116 static char * sel_to_char(uint64_t sel
)
1119 case SERVICE_STASH_SET_KEY
:
1121 case SERVICE_STASH_GET_KEY
:
1123 case SERVICE_STASH_BLOB
:
1124 return "stash_blob";
1125 case SERVICE_KB_LOAD
:
1127 case SERVICE_KB_SAVE
:
1129 case SERVICE_KB_UNLOCK
:
1131 case SERVICE_KB_LOCK
:
1133 case SERVICE_KB_CHANGE_SECRET
:
1134 return "kb_change_secret";
1135 case SERVICE_KB_CREATE
:
1137 case SERVICE_KB_IS_LOCKED
:
1138 return "kb_is_locked";
1139 case SERVICE_KB_RESET
:
1141 case SERVICE_KB_UNLOAD
:
1143 case SERVICE_KB_LOAD_UID
:
1144 return "kb_load_uid";
1145 case SERVICE_KB_WRAP_KEY
:
1146 return "kb_wrap_key";
1147 case SERVICE_KB_UNWRAP_KEY
:
1148 return "kb_unwrap_key";
1154 static char * err_to_char(int err
)
1159 case KB_GeneralError
:
1160 return "general error";
1161 case KB_BagNotFound
:
1162 return "bag not found";
1165 case KB_BagNotLoaded
:
1166 return "bag not loaded";
1168 return "bag exists";
1169 case KB_InvalidSession
:
1170 return "invalid session";
1176 static bool log_kcv(uint64_t request
)
1178 if ((request
== SERVICE_KB_CREATE
) ||
1179 (request
== SERVICE_KB_LOAD
) ||
1180 (request
== SERVICE_KB_SAVE
) ||
1181 (request
== SERVICE_KB_UNLOCK
) ||
1182 (request
== SERVICE_KB_CHANGE_SECRET
) ||
1183 (request
== SERVICE_KB_RESET
) ||
1184 (request
== SERVICE_KB_IS_LOCKED
) ||
1185 (request
== SERVICE_STASH_GET_KEY
) ||
1186 (request
== SERVICE_STASH_SET_KEY
) ||
1187 (request
== SERVICE_STASH_LOAD_KEY
) ||
1188 (request
== SERVICE_KB_LOAD_UID
) ||
1189 (request
== SERVICE_KB_WRAP_KEY
) ||
1190 (request
== SERVICE_KB_UNWRAP_KEY
)) {
1197 void service_peer_event_handler(xpc_connection_t connection
, xpc_object_t event
)
1199 xpc_type_t type
= xpc_get_type(event
);
1202 if (type
== XPC_TYPE_ERROR
) {
1203 if (event
== XPC_ERROR_CONNECTION_INVALID
) {
1206 assert(type
== XPC_TYPE_DICTIONARY
);
1208 int rc
= KB_GeneralError
;
1209 uint64_t request
= 0;
1210 const uint8_t * secret
= NULL
, * new_secret
= NULL
;
1211 size_t secret_len
= 0, new_secret_len
= 0, data_len
= 0;
1212 service_context_t
* context
= NULL
;
1213 bool free_context
= false;
1215 const char *entitlement
;
1217 xpc_object_t reply
= xpc_dictionary_create_reply(event
);
1219 request
= xpc_dictionary_get_uint64(event
, SERVICE_XPC_REQUEST
);
1222 // For SERVICE_KB_{UNLOAD,LOAD} only, allow non-securityd, non-root but
1223 // entitled callers.
1224 if (request
== SERVICE_KB_UNLOAD
|| request
== SERVICE_KB_LOAD_UID
) {
1226 case SERVICE_KB_UNLOAD
:
1227 entitlement
= "com.apple.private.securityd.keybag-unload";
1229 case SERVICE_KB_LOAD_UID
:
1230 entitlement
= "com.apple.private.securityd.keybag-load";
1233 if (!peer_has_entitlement(connection
, entitlement
) && !peer_has_entitlement(connection
, "com.apple.keystore.device")) {
1234 xpc_connection_cancel(connection
);
1238 if (xpc_connection_get_euid(connection
) != 0) {
1239 xpc_connection_cancel(connection
);
1242 if (!check_signature(connection
)) {
1243 xpc_connection_cancel(connection
);
1248 data
= xpc_dictionary_get_data(event
, SERVICE_XPC_CONTEXT
, &data_len
);
1249 require_action(data
|| request
== SERVICE_KB_UNLOAD
|| request
== SERVICE_KB_LOAD_UID
, done
, rc
= KB_GeneralError
);
1251 require(data_len
== sizeof(service_context_t
), done
);
1252 context
= (service_context_t
*)data
;
1254 audit_token_t audit_token
= { 0 };
1255 xpc_connection_get_audit_token(connection
, &audit_token
);
1256 context
= calloc(1, sizeof(service_context_t
));
1257 context
->s_id
= xpc_connection_get_asid(connection
);
1258 context
->s_uid
= xpc_connection_get_euid(connection
);
1259 context
->procToken
= audit_token
;
1260 free_context
= true;
1264 require_action(context
->s_id
!= AU_DEFAUDITSID
, done
, rc
= KB_InvalidSession
);
1265 require_action(context
->s_uid
!= AU_DEFAUDITID
, done
, rc
= KB_InvalidSession
); // we only want to work in actual user sessions.
1268 case SERVICE_KB_CREATE
:
1269 secret
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET
, &secret_len
);
1270 rc
= service_kb_create(context
, secret
, (int)secret_len
);
1272 case SERVICE_KB_LOAD
:
1273 rc
= service_kb_load(context
);
1275 case SERVICE_KB_UNLOAD
:
1276 rc
= service_kb_unload(context
);
1278 case SERVICE_KB_SAVE
:
1279 rc
= service_kb_save(context
);
1281 case SERVICE_KB_UNLOCK
:
1282 secret
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET
, &secret_len
);
1283 rc
= service_kb_unlock(context
, secret
, (int)secret_len
);
1285 case SERVICE_KB_LOCK
:
1286 rc
= service_kb_lock(context
);
1288 case SERVICE_KB_CHANGE_SECRET
:
1289 secret
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET
, &secret_len
);
1290 new_secret
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET_NEW
, &new_secret_len
);
1291 rc
= service_kb_change_secret(context
, secret
, (int)secret_len
, new_secret
, (int)new_secret_len
);
1293 case SERVICE_KB_RESET
:
1294 secret
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET
, &secret_len
);
1295 rc
= service_kb_reset(context
, secret
, (int)secret_len
);
1297 case SERVICE_KB_IS_LOCKED
:
1298 rc
= service_kb_is_locked(context
, reply
);
1300 case SERVICE_STASH_GET_KEY
:
1301 rc
= service_stash_get_key(context
, event
, reply
);
1303 case SERVICE_STASH_SET_KEY
:
1304 rc
= service_stash_set_key(context
, event
, reply
);
1306 case SERVICE_STASH_LOAD_KEY
:
1307 rc
= service_stash_load_key(context
, event
, reply
);
1309 case SERVICE_KB_LOAD_UID
:
1310 uid
= (uid_t
)xpc_dictionary_get_uint64(event
, SERVICE_XPC_UID
);
1311 rc
= service_kb_load_uid(uid
, &context
->kcv
);
1313 case SERVICE_KB_WRAP_KEY
:
1314 rc
= service_kb_wrap_key(context
, event
, reply
);
1316 case SERVICE_KB_UNWRAP_KEY
:
1317 rc
= service_kb_unwrap_key(context
, event
, reply
);
1320 case SERVICE_STASH_BLOB
:
1321 rc
= service_stash_blob(event
, reply
);
1325 LOG("unknown service type");
1331 char log
[200] = { 0 };
1332 int count
= snprintf(log
, sizeof(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);
1333 if (log_kcv(request
) && (count
< sizeof(log
) - 1) && (count
> 0) && (context
) && (context
->kcv
> 0)) {
1334 count
= snprintf(log
+ count
, sizeof(log
) - count
, ", kcv: 0x%0llx", context
->kcv
);
1338 LOG("%{public}s", log
);
1340 if ((rc
!= 0) || log_kcv(request
)) {
1341 os_log(OS_LOG_DEFAULT
, "%{public}s", log
);
1346 xpc_dictionary_set_int64(reply
, SERVICE_XPC_RC
, rc
);
1347 xpc_connection_send_message(connection
, reply
);
1355 bool check_signature(xpc_connection_t connection
)
1357 #if !(DEBUG || RC_BUILDIT_YES)
1358 audit_token_t token
;
1360 xpc_connection_get_audit_token(connection
, &token
);
1362 SecTaskRef task
= SecTaskCreateWithAuditToken(NULL
, token
);
1364 os_log(OS_LOG_DEFAULT
, "failed getting SecTaskRef of the client");
1368 uint32_t flags
= SecTaskGetCodeSignStatus(task
);
1369 /* check if valid and platform binary, but not platform path */
1372 if ((flags
& (CS_VALID
| CS_PLATFORM_BINARY
| CS_PLATFORM_PATH
)) != (CS_VALID
| CS_PLATFORM_BINARY
)) {
1373 if (SecIsInternalRelease()) {
1374 if ((flags
& (CS_DEBUGGED
| CS_PLATFORM_BINARY
| CS_PLATFORM_PATH
)) != (CS_DEBUGGED
| CS_PLATFORM_BINARY
)) {
1375 os_log(OS_LOG_DEFAULT
, "client is not a platform binary: 0x%08x", flags
);
1380 os_log(OS_LOG_DEFAULT
, "client is not a platform binary: 0x%08x", flags
);
1386 CFStringRef signingIdentity
= SecTaskCopySigningIdentifier(task
, NULL
);
1388 if (signingIdentity
== NULL
) {
1389 os_log(OS_LOG_DEFAULT
, "client have no code sign identity");
1393 bool res
= CFEqual(signingIdentity
, CFSTR("com.apple.securityd"));
1394 CFRelease(signingIdentity
);
1397 os_log(OS_LOG_DEFAULT
, "client is not not securityd");
1405 static void register_for_notifications()
1407 __block kern_return_t kr
;
1408 static mach_port_t mp
= MACH_PORT_NULL
;
1410 static dispatch_once_t onceToken
= 0;
1411 dispatch_once(&onceToken
, ^{
1412 kr
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &mp
);
1413 if (kr
== KERN_SUCCESS
) {
1414 dispatch_source_t mach_src
= dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV
, mp
, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0));
1415 dispatch_source_set_event_handler(mach_src
, ^{
1416 mach_msg_return_t mr
;
1417 uint8_t buf
[sizeof(aks_notification_msg_t
) + MAX_TRAILER_SIZE
] = {};
1418 aks_notification_msg_t
* msg
= (aks_notification_msg_t
*)buf
;
1419 mr
= mach_msg((mach_msg_header_t
*)&buf
, MACH_RCV_MSG
, 0, sizeof(buf
), mp
, MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
1420 if (mr
== MACH_MSG_SUCCESS
&& msg
->hdr
.msgh_id
== AKS_NOTIFICATION_MSGID
) {
1422 } else if (mr
== MACH_MSG_SUCCESS
&& msg
->hdr
.msgh_id
== AKS_NOTIFICATION_WRITE_SYSTEM_KEYBAG
) {
1423 os_log(OS_LOG_DEFAULT
, "request to update handle %d", msg
->handle
);
1424 update_keybag_handle(msg
->handle
);
1426 os_log(OS_LOG_DEFAULT
, "mach_msg error: %x", mr
);
1429 dispatch_resume(mach_src
);
1431 os_log(OS_LOG_DEFAULT
, "failed to create notification port");
1436 kr
= aks_register_for_notifications(mp
, AKS_NOTIFICATION_WRITE_SYSTEM_KEYBAG
);
1437 if (kr
== KERN_SUCCESS
) {
1438 os_log(OS_LOG_DEFAULT
, "registered for notifications");
1440 os_log(OS_LOG_DEFAULT
, "failed to register for notifications %d", kr
);
1444 int main(int argc
, const char * argv
[])
1447 if (sandbox_init(SECURITYD_SERVICE_NAME
, SANDBOX_NAMED
, &errorbuf
) != 0) {
1448 os_log(OS_LOG_DEFAULT
, "sandbox_init failed %{public}s", errorbuf
);
1449 sandbox_free_error(errorbuf
);
1455 register_for_notifications();
1457 xpc_connection_t listener
= xpc_connection_create_mach_service(SECURITYD_SERVICE_NAME
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1458 xpc_connection_set_event_handler(listener
, ^(xpc_object_t peer
) {
1459 // It is safe to cast 'peer' to xpc_connection_t assuming
1460 // we have a correct configuration in our launchd.plist.
1461 xpc_connection_set_event_handler(peer
, ^(xpc_object_t event
) {
1462 xpc_transaction_begin();
1463 service_peer_event_handler(peer
, event
);
1464 xpc_transaction_end();
1466 xpc_connection_resume(peer
);
1468 xpc_connection_resume(listener
);