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> 
  30 #include <IOKit/IOKitLib.h> 
  31 #include <Kernel/IOKit/crypto/AppleFDEKeyStoreDefs.h> 
  34 #define LOG(...)    syslog(LOG_ERR, ##__VA_ARGS__); 
  39 static bool check_signature(xpc_connection_t connection
); 
  41 static pid_t 
get_caller_pid(audit_token_t 
* token
) 
  45         audit_token_to_au32(*token
, NULL
, NULL
, NULL
, NULL
, NULL
, &pid
, NULL
, NULL
); 
  50 // exported from libaks.a 
  51 kern_return_t 
aks_register_for_notifications(mach_port_t server_port
, uintptr_t message_id
); 
  52 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
); 
  54 const char * kb_home_path 
= "Library/Keychains"; 
  55 const char * kb_user_bag 
= "user.kb"; 
  56 const char * kb_stash_bag 
= "stash.kb"; 
  58 #define HEXBUF_LEN 2048 
  65 } service_user_record_t
; 
  75     io_registry_entry_t service
; 
  79     service 
= IOServiceGetMatchingService(kIOMasterPortDefault
, IOServiceMatching(kAppleFDEKeyStoreServiceName
)); 
  80     if (service 
== IO_OBJECT_NULL
) 
  81         return IO_OBJECT_NULL
; 
  83     kr 
= IOServiceOpen(service
, mach_task_self(), 0, &conn
); 
  84     if (kr 
!= KERN_SUCCESS
) 
  85         return IO_OBJECT_NULL
; 
  87     kr 
= IOConnectCallMethod(conn
, kAppleFDEKeyStoreUserClientOpen
, NULL
, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
); 
  88     if (kr 
!= KERN_SUCCESS
) { 
  90         return IO_OBJECT_NULL
; 
  97 closeiodev(io_connect_t conn
) 
 100     kr 
= IOConnectCallMethod(conn
, kAppleFDEKeyStoreUserClientClose
, NULL
, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
); 
 101     if (kr 
!= KERN_SUCCESS
) 
 103     IOServiceClose(conn
); 
 106 static dispatch_queue_t
 
 107 _kb_service_get_dispatch_queue() 
 109     static dispatch_once_t onceToken 
= 0; 
 110     static dispatch_queue_t connection_queue 
= NULL
; 
 112     dispatch_once(&onceToken
, ^{ 
 113         connection_queue 
= dispatch_queue_create("kb-service-queue", DISPATCH_QUEUE_SERIAL
); 
 116     return connection_queue
; 
 119 static service_user_record_t 
* get_user_record(uid_t uid
) 
 121     service_user_record_t 
* ur 
= NULL
; 
 123     if ((bufsize 
= sysconf(_SC_GETPW_R_SIZE_MAX
)) == -1) { 
 127     struct passwd pwbuf
, *pw 
= NULL
; 
 128     if ((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         syslog(LOG_ERR
, "failed to lookup user record for uid: %d", uid
); 
 143 static void free_user_record(service_user_record_t 
* ur
) 
 156 static const char * get_host_uuid() 
 158     static uuid_string_t hostuuid 
= {}; 
 159     static dispatch_once_t onceToken
; 
 160     dispatch_once(&onceToken
, ^{ 
 161         struct timespec timeout 
= {30, 0}; 
 163         if (gethostuuid(uuid
, &timeout
) == 0) { 
 164             uuid_unparse(uuid
, hostuuid
); 
 166             syslog(LOG_ERR
, "failed to get host uuid"); 
 174 _kb_copy_bag_filename(service_user_record_t 
* ur
, kb_bag_type_t type
) 
 176     char * bag_file 
= NULL
; 
 177     const char * name 
= NULL
; 
 181         case kb_bag_type_user
: 
 184         case kb_bag_type_stash
: 
 191     bag_file 
= calloc(1u, PATH_MAX
); 
 192     require(bag_file
, done
); 
 194     snprintf(bag_file
, PATH_MAX
, "%s/%s/%s/%s", ur
->home
, kb_home_path
, get_host_uuid(), name
); 
 201 _kb_verify_create_path(service_user_record_t 
* ur
) 
 203     bool created 
= false; 
 204     struct stat st_info 
= {}; 
 205     char new_path
[PATH_MAX
] = {}; 
 206     char kb_path
[PATH_MAX
] = {}; 
 207     snprintf(kb_path
, sizeof(kb_path
), "%s/%s/%s", ur
->home
, kb_home_path
, get_host_uuid()); 
 208     if (lstat(kb_path
, &st_info
) == 0) { 
 209         if (S_ISDIR(st_info
.st_mode
)) { 
 212             syslog(LOG_ERR
, "invalid directory at '%s' moving aside", kb_path
); 
 213             snprintf(new_path
, sizeof(new_path
), "%s-invalid", kb_path
); 
 215             if (rename(kb_path
, new_path
) != 0) { 
 216                 syslog(LOG_ERR
, "failed to rename file: %s (%s)", kb_path
, strerror(errno
)); 
 222         require_action(mkpath_np(kb_path
, 0700) == 0, done
, syslog(LOG_ERR
, "could not create path: %s (%s)", kb_path
, strerror(errno
))); 
 231 _set_thread_credentials(service_user_record_t 
* ur
) 
 233     int rc 
= pthread_setugid_np(ur
->uid
, ur
->gid
); 
 234     if (rc
) { syslog(LOG_ERR
, "failed to set thread credential: %i (%s)", errno
, strerror(errno
)); } 
 236     rc 
= initgroups(ur
->name
, ur
->gid
); 
 237     if (rc
) { syslog(LOG_ERR
, "failed to initgroups: %i", rc
); } 
 241 _clear_thread_credentials() 
 243     int rc 
= pthread_setugid_np(KAUTH_UID_NONE
, KAUTH_GID_NONE
); 
 244     if (rc
) { syslog(LOG_ERR
, "failed to reset thread credential: %i (%s)", errno
, strerror(errno
)); } 
 248 _kb_bag_exists(service_user_record_t 
* ur
, const char * bag_file
) 
 251     struct stat st_info 
= {}; 
 252     char new_file
[PATH_MAX
] = {}; 
 256     _set_thread_credentials(ur
); 
 257     if (lstat(bag_file
, &st_info
) == 0) { 
 258         if (S_ISREG(st_info
.st_mode
)) { 
 261             syslog(LOG_ERR
, "invalid file at '%s' moving aside", bag_file
); 
 262             snprintf(new_file
, sizeof(new_file
), "%s-invalid", bag_file
); 
 264             if (rename(bag_file
, new_file
) != 0) { 
 265                 syslog(LOG_ERR
, "failed to rename file: %s (%s)", bag_file
, strerror(errno
)); 
 271     _clear_thread_credentials(); 
 276 _kb_save_bag_to_disk(service_user_record_t 
* ur
, const char * bag_file
, void * data
, size_t length
) 
 281     require(bag_file
, done
); 
 283     _set_thread_credentials(ur
); 
 284     require(_kb_verify_create_path(ur
), done
); 
 286     fd 
= open(bag_file
, O_CREAT 
| O_TRUNC 
| O_WRONLY 
| O_NOFOLLOW
, 0600); 
 287     require_action(fd 
!= -1, done
, syslog(LOG_ERR
, "could not create file: %s (%s)", bag_file
, strerror(errno
))); 
 288     require_action(write(fd
, data
, length
) != -1, done
, syslog(LOG_ERR
, "failed to write keybag to disk %s", strerror(errno
))); 
 293     if (fd 
!= -1) { close(fd
); } 
 294     _clear_thread_credentials(); 
 299 _kb_load_bag_from_disk(service_user_record_t 
* ur
, const char * bag_file
, uint8_t ** data
, size_t * length
) 
 303     uint8_t * buf 
= NULL
; 
 305     struct stat st_info 
= {}; 
 307     require(bag_file
, done
); 
 309     _set_thread_credentials(ur
); 
 310     require(_kb_verify_create_path(ur
), done
); 
 311     require_quiet(lstat(bag_file
, &st_info
) == 0, done
); 
 312     require_action(S_ISREG(st_info
.st_mode
), done
, syslog(LOG_ERR
, "failed to load, not a file: %s", bag_file
)); 
 313     buf_size 
= (size_t)st_info
.st_size
; 
 315     fd 
= open(bag_file
, O_RDONLY 
| O_NOFOLLOW
); 
 316     require_action(fd 
!= -1, done
, syslog(LOG_ERR
, "could not open file: %s (%s)", bag_file
, strerror(errno
))); 
 318     buf 
= (uint8_t *)calloc(1u, buf_size
); 
 319     require(buf 
!= NULL
, done
); 
 320     require(read(fd
, buf
, buf_size
) == buf_size
, done
); 
 328     if (fd 
!= -1) { close(fd
); } 
 329     if (buf
) { free(buf
); } 
 330     _clear_thread_credentials(); 
 335 _kb_rename_bag_on_disk(service_user_record_t 
* ur
, const char * bag_file
) 
 337     char new_file
[PATH_MAX
] = {}; 
 339         _set_thread_credentials(ur
); 
 340         snprintf(new_file
, sizeof(new_file
), "%s-invalid", bag_file
); 
 342         rename(bag_file
, new_file
); 
 343         _clear_thread_credentials(); 
 348 _kb_delete_bag_on_disk(service_user_record_t 
* ur
, const char * bag_file
) 
 351         _set_thread_credentials(ur
); 
 353         _clear_thread_credentials(); 
 357 static int service_kb_load(service_context_t 
*context
); 
 358 static int service_kb_load_uid(uid_t s_uid
); 
 361 _kb_get_session_handle(service_context_t 
* context
, keybag_handle_t 
* handle_out
) 
 363     int rc 
= KB_BagNotLoaded
; 
 364     require_noerr_quiet(aks_get_system(context
->s_uid
, handle_out
), done
); 
 369     if (rc 
== KB_BagNotLoaded
) { 
 370         if (service_kb_load(context
) == KB_Success
) { 
 371             if (aks_get_system(context
->s_uid
, handle_out
) == kIOReturnSuccess
) { 
 379 static void update_keybag_handle(keybag_handle_t handle
) 
 381     dispatch_sync(_kb_service_get_dispatch_queue(), ^{ 
 382         uid_t uid 
= abs(handle
); 
 383         uint8_t * buf 
= NULL
; 
 385         service_user_record_t 
* ur 
= NULL
; 
 386         char * bag_file 
= NULL
; 
 388         require_noerr(aks_save_bag(handle
, (void**)&buf
, (int*)&buf_size
), done
); 
 389         require(ur 
= get_user_record(uid
), done
); 
 390         require(bag_file 
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
); 
 391         require(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
), done
); 
 393         syslog(LOG_NOTICE
, "successfully updated handle %d", handle
); 
 397         if (ur
) free_user_record(ur
); 
 398         if (bag_file
) free(bag_file
); 
 403 service_kb_create(service_context_t 
* context
, const void * secret
, int secret_len
) 
 405     __block 
int rc 
= KB_GeneralError
; 
 407     dispatch_sync(_kb_service_get_dispatch_queue(), ^{ 
 408         uint8_t * buf 
= NULL
; 
 410         keybag_handle_t session_handle 
= bad_keybag_handle
; 
 411         service_user_record_t 
* ur 
= get_user_record(context
->s_uid
); 
 412         char * bag_file 
= _kb_copy_bag_filename(ur
, kb_bag_type_user
); 
 414         require(bag_file
, done
); 
 416         // check for the existance of the bagfile 
 417         require_action(!_kb_bag_exists(ur
, bag_file
), done
, rc 
= KB_BagExists
); 
 419         require_noerr(rc 
= aks_create_bag(secret
, secret_len
, kAppleKeyStoreDeviceBag
, &session_handle
), done
); 
 420         require_noerr(rc 
= aks_save_bag(session_handle
, (void**)&buf
, (int*)&buf_size
), done
); 
 421         require_action(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
), done
, rc 
= KB_BagError
); 
 422         require_noerr(rc 
= aks_set_system(session_handle
, context
->s_uid
), done
); 
 423         aks_unload_bag(session_handle
); 
 424         require_noerr(rc 
= _kb_get_session_handle(context
, &session_handle
), done
); 
 426         if (secret 
&& rc 
== KB_Success
) { 
 427             aks_unlock_bag(session_handle
, secret
, secret_len
); 
 432         if (bag_file
) { free(bag_file
); } 
 433         if (ur
) free_user_record(ur
); 
 439 /* Load s_uid's keybag, unless already loaded */ 
 441 _service_kb_load_uid(uid_t s_uid
) 
 443     __block 
int rc 
= KB_GeneralError
; 
 445     dispatch_sync(_kb_service_get_dispatch_queue(), ^{ 
 446         uint8_t * buf 
= NULL
; 
 448         keybag_handle_t session_handle 
= bad_keybag_handle
; 
 449         service_user_record_t 
* ur 
= NULL
; 
 450         char * bag_file 
= NULL
; 
 452         rc 
= aks_get_system(s_uid
, &session_handle
); 
 453         if (rc 
== kIOReturnNotFound
) { 
 454             require_action(ur 
= get_user_record(s_uid
), done
, rc 
= KB_GeneralError
); 
 455             require_action(bag_file 
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
, rc 
= KB_GeneralError
); 
 456             require_action_quiet(_kb_load_bag_from_disk(ur
, bag_file
, &buf
, &buf_size
), done
, rc 
= KB_BagNotFound
); 
 457             rc 
= aks_load_bag(buf
, (int)buf_size
, &session_handle
); 
 458             if (rc 
== kIOReturnNotPermitted
) { 
 459                 syslog(LOG_ERR
, "error loading keybag for uid (%i)", s_uid
); 
 460                 _kb_rename_bag_on_disk(ur
, bag_file
); 
 463             require_noerr(rc
, done
); 
 464             require_noerr(rc 
= aks_set_system(session_handle
, s_uid
), done
); 
 465             aks_unload_bag(session_handle
); 
 467         require(rc 
== KB_Success
, done
); 
 471         if (ur
) free_user_record(ur
); 
 472         if (bag_file
) free(bag_file
); 
 479 service_kb_load_uid(uid_t s_uid
) 
 481     return _service_kb_load_uid(s_uid
); 
 485 service_kb_load(service_context_t 
* context
) 
 487     return _service_kb_load_uid(context
->s_uid
); 
 491 service_kb_unload(service_context_t 
*context
) 
 493     __block 
int rc 
= KB_GeneralError
; 
 495     dispatch_sync(_kb_service_get_dispatch_queue(), ^{ 
 496         keybag_handle_t session_handle 
= bad_keybag_handle
; 
 498         rc 
= aks_get_system(context
->s_uid
, &session_handle
); 
 499         if (rc 
== kIOReturnNotFound
) { 
 500             // No session bag, nothing to do 
 503         } else if (rc 
!= kIOReturnSuccess
) { 
 504             syslog(LOG_ERR
, "error locating session keybag for uid (%i) in session (%i)", context
->s_uid
, context
->s_id
); 
 509         rc 
= aks_unload_bag(session_handle
); 
 510         if (rc 
!= kAKSReturnSuccess
) { 
 511             syslog(LOG_ERR
, "error unloading keybag for uid (%i) in session (%i)", context
->s_uid
, context
->s_id
); 
 514             syslog(LOG_ERR
, "successfully unloaded keybag (%ld) for uid (%i) in session (%i)", (long)session_handle
, context
->s_uid
, context
->s_id
); 
 522 service_kb_save(service_context_t 
* context
) 
 524     __block 
int rc 
= KB_GeneralError
; 
 525     keybag_handle_t session_handle
; 
 526     require_noerr(rc 
= _kb_get_session_handle(context
, &session_handle
), done
); 
 528     dispatch_sync(_kb_service_get_dispatch_queue(), ^{ 
 529         uint8_t * buf 
= NULL
; 
 531         service_user_record_t 
* ur 
= NULL
; 
 532         char * bag_file 
= NULL
; 
 534         require_noerr(rc 
= aks_save_bag(session_handle
, (void**)&buf
, (int*)&buf_size
), done
); 
 535         require_action(ur 
= get_user_record(context
->s_uid
), done
, rc 
= KB_GeneralError
); 
 536         require_action(bag_file 
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
, rc 
= KB_GeneralError
); 
 537         require_action(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
), done
, rc 
= KB_BagError
); 
 543         if (ur
) free_user_record(ur
); 
 544         if (bag_file
) free(bag_file
); 
 553 service_kb_unlock(service_context_t 
* context
, const void * secret
, int secret_len
) 
 555     int rc 
= KB_GeneralError
; 
 556     keybag_handle_t session_handle
; 
 557     require_noerr(rc 
= _kb_get_session_handle(context
, &session_handle
), done
); 
 559     rc 
= aks_unlock_bag(session_handle
, secret
, secret_len
); 
 562     syslog(LOG_NOTICE
, "aks_unlock_bag result: (%ld)", (long)rc
); 
 567 service_kb_lock(service_context_t 
* context
) 
 569     // this call has been disabled 
 574 service_kb_change_secret(service_context_t 
* context
, const void * secret
, int secret_len
, const void * new_secret
, int new_secret_len
) 
 576     __block 
int rc 
= KB_GeneralError
; 
 577     keybag_handle_t session_handle
; 
 578     require_noerr(rc 
= _kb_get_session_handle(context
, &session_handle
), done
); 
 580     dispatch_sync(_kb_service_get_dispatch_queue(), ^{ 
 581         uint8_t * buf 
= NULL
; 
 583         service_user_record_t 
* ur 
= NULL
; 
 584         char * bag_file 
= NULL
; 
 586         require_noerr(rc 
= aks_change_secret(session_handle
, secret
, secret_len
, new_secret
, new_secret_len
, NULL
, NULL
), done
); 
 587         require_noerr(rc 
= aks_save_bag(session_handle
, (void**)&buf
, (int*)&buf_size
), done
); 
 588         require_action(ur 
= get_user_record(context
->s_uid
), done
, rc 
= KB_GeneralError
); 
 589         require_action(bag_file 
= _kb_copy_bag_filename(ur
, kb_bag_type_user
), done
, rc 
= KB_GeneralError
); 
 590         require_action(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
), done
, rc 
= KB_BagError
); 
 596         if (ur
) free_user_record(ur
); 
 597         if (bag_file
) free(bag_file
); 
 606 service_kb_reset(service_context_t 
* context
, const void * secret
, int secret_len
) 
 608     __block 
int rc 
= KB_GeneralError
; 
 609     service_user_record_t 
* ur 
= NULL
; 
 610     char * bag_file 
= NULL
; 
 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
); 
 615     dispatch_sync(_kb_service_get_dispatch_queue(), ^{ 
 616         uint8_t * buf 
= NULL
; 
 618         keybag_handle_t session_handle 
= bad_keybag_handle
; 
 620         syslog(LOG_ERR
, "resetting keybag for uid (%i) in session (%i)", context
->s_uid
, context
->s_id
); 
 621         _kb_rename_bag_on_disk(ur
, bag_file
); 
 623         require_noerr(rc 
= aks_create_bag(secret
, secret_len
, kAppleKeyStoreDeviceBag
, &session_handle
), done
); 
 624         require_noerr(rc 
= aks_save_bag(session_handle
, (void**)&buf
, (int*)&buf_size
), done
); 
 625         require_action(_kb_save_bag_to_disk(ur
, bag_file
, buf
, buf_size
), done
, rc 
= KB_BagError
); 
 626         require_noerr(rc 
= aks_set_system(session_handle
, context
->s_uid
), done
); 
 627         aks_unload_bag(session_handle
); 
 628         require_noerr(rc 
= _kb_get_session_handle(context
, &session_handle
), done
); 
 630         if (secret 
&& rc 
== KB_Success
) { 
 631             aks_unlock_bag(session_handle
, secret
, secret_len
); 
 640     if (ur
) free_user_record(ur
); 
 641     if (bag_file
) free(bag_file
); 
 646 service_kb_is_locked(service_context_t 
* context
, xpc_object_t reply
) 
 648     int rc 
= KB_GeneralError
; 
 649     keybag_state_t state
; 
 650     keybag_handle_t session_handle
; 
 651     require_noerr(rc 
= _kb_get_session_handle(context
, &session_handle
), done
); 
 653     require_noerr(rc 
= aks_get_lock_state(session_handle
, &state
), done
); 
 655     xpc_dictionary_set_bool(reply
, SERVICE_XPC_LOCKED
, state 
& keybag_state_locked
); 
 656     xpc_dictionary_set_bool(reply
, SERVICE_XPC_NO_PIN
, state 
& keybag_state_no_pin
); 
 663 service_kb_stash_create(service_context_t 
* context
, const void * key
, unsigned key_size
) 
 665     int rc 
= KB_GeneralError
; 
 666     char * bag_file 
= NULL
; 
 667     keybag_handle_t session_handle
; 
 668     service_user_record_t 
* ur 
= NULL
; 
 669     void * stashbag 
= NULL
; 
 670     int stashbag_size 
= 0; 
 671     __block 
bool saved 
= false; 
 674     require_noerr(rc 
= _kb_get_session_handle(context
, &session_handle
), done
); 
 675     require_action(ur 
= get_user_record(context
->s_uid
), done
, rc 
= KB_GeneralError
); 
 676     require_noerr(rc 
= aks_stash_escrow(session_handle
, true, key
, key_size
, NULL
, 0, (void**)&stashbag
, &stashbag_size
), done
); 
 677     require_action(bag_file 
= _kb_copy_bag_filename(ur
, kb_bag_type_stash
), done
, rc 
= KB_GeneralError
); 
 679     // sync writing the bag to disk 
 680     dispatch_sync(_kb_service_get_dispatch_queue(), ^{ 
 681         saved 
= _kb_save_bag_to_disk(ur
, bag_file
, stashbag
, stashbag_size
); 
 683     require_action(saved
, done
, rc 
= KB_BagError
); 
 687     if (stashbag
) { free(stashbag
); } 
 688     if (bag_file
) { free(bag_file
); } 
 689     if (ur
) free_user_record(ur
); 
 694 service_kb_stash_load(service_context_t 
* context
, const void * key
, unsigned key_size
, bool nondestructive
) 
 696     __block 
int rc 
= KB_GeneralError
; 
 697     char * bag_file 
= NULL
; 
 698     keybag_handle_t session_handle
; 
 699     service_user_record_t 
* ur 
= NULL
; 
 700     __block 
uint8_t * stashbag 
= NULL
; 
 701     __block 
size_t stashbag_size 
= 0; 
 704     require_noerr(rc 
= _kb_get_session_handle(context
, &session_handle
), done
); 
 705     require_action(ur 
= get_user_record(context
->s_uid
), done
, rc 
= KB_GeneralError
); 
 706     require_action(bag_file 
= _kb_copy_bag_filename(ur
, kb_bag_type_stash
), done
, rc 
= KB_GeneralError
); 
 708     // sync loading the bag from disk 
 709     dispatch_sync(_kb_service_get_dispatch_queue(), ^{ 
 710         if (!_kb_load_bag_from_disk(ur
, bag_file
, &stashbag
, &stashbag_size
)) { 
 714     require_noerr(rc
, done
); 
 716     require_noerr(rc 
= aks_stash_escrow(session_handle
, false, key
, key_size
, stashbag
, (int)stashbag_size
, NULL
, NULL
), done
); 
 720     if (stashbag
) { free(stashbag
); } 
 721     if ((bag_file
) && (!nondestructive
)) { 
 722         _kb_delete_bag_on_disk(ur
, bag_file
); 
 725     if (ur
) free_user_record(ur
); 
 730 // Get the keychain master key from the AppleFDEKeyStore. 
 731 // Note that this is a one-time call - the master key is 
 732 // removed from the keystore after it is returned. 
 733 // Requires the entitlement: com.apple.private.securityd.keychain 
 735 OSStatus 
service_stash_get_key(service_context_t 
* context
, xpc_object_t event
, xpc_object_t reply
) 
 737     getStashKey_InStruct_t inStruct
; 
 738     getStashKey_OutStruct_t outStruct
; 
 739     size_t outSize 
= sizeof(outStruct
); 
 740     kern_return_t kr 
= KERN_INVALID_ARGUMENT
; 
 742     io_connect_t conn 
= openiodev(); 
 744     inStruct
.type 
= kAppleFDEKeyStoreStash_master
; 
 746     kr 
= IOConnectCallMethod(conn
, kAppleFDEKeyStore_getStashKey
, 
 748                              &inStruct
, sizeof(inStruct
), 
 750                              &outStruct
, &outSize
); 
 752     if (kr 
== KERN_SUCCESS
) { 
 753         xpc_dictionary_set_data(reply
, SERVICE_XPC_KEY
, outStruct
.outBuf
.key
.key
, outStruct
.outBuf
.key
.keysize
); 
 754         service_kb_stash_load(context
, outStruct
.outBuf
.key
.key
, outStruct
.outBuf
.key
.keysize
, false); 
 765 // Stash the keychain master key in the AppleFDEKeyStore and 
 766 // flag it as the keychain master key to be added to the 
 767 // reboot NVRAM blob. 
 768 // This requires two calls to the AKS: the first to store the 
 769 // key and get its uuid.  The second uses the uuid to flag the 
 770 // key for blob inclusion. 
 772 OSStatus 
service_stash_set_key(service_context_t 
* context
, xpc_object_t event
, xpc_object_t reply
) 
 774     kern_return_t kr 
= KERN_INVALID_ARGUMENT
; 
 775     io_connect_t conn 
= IO_OBJECT_NULL
; 
 776     size_t keydata_len 
= 0; 
 779     keybag_state_t state
; 
 780     keybag_handle_t session_handle
; 
 781     require_noerr(_kb_get_session_handle(context
, &session_handle
), done
); 
 782     require_noerr(aks_get_lock_state(session_handle
, &state
), done
); 
 783     require_action(!(state 
& keybag_lock_locked
), done
, kr 
= CSSMERR_CSP_OS_ACCESS_DENIED
; LOG("stash failed keybag locked")); 
 788     // Store the key in the keystore and get its uuid 
 789     setKeyGetUUID_InStruct_t inStruct1
; 
 790     uuid_OutStruct_t outStruct1
; 
 793     const uint8_t *keydata 
= xpc_dictionary_get_data(event
, SERVICE_XPC_KEY
, &keydata_len
); 
 794     require(keydata
, done
); 
 796     memcpy(&inStruct1
.inKey
.key
.key
, keydata
, keydata_len
); 
 797     inStruct1
.inKey
.key
.keysize 
= (cryptosize_t
) keydata_len
; 
 798     len 
= sizeof(outStruct1
); 
 799     kr 
= IOConnectCallMethod(conn
, kAppleFDEKeyStore_setKeyGetUUID
, 
 801                              &inStruct1
, sizeof(inStruct1
), 
 804     require(kr 
== KERN_SUCCESS
, done
); 
 806     // Now using the uuid stash it as the master key 
 807     setStashKey_InStruct_t inStruct2
; 
 808     memcpy(&inStruct2
.uuid
, &outStruct1
.uuid
, sizeof(outStruct1
.uuid
)); 
 809     inStruct2
.type  
= kAppleFDEKeyStoreStash_master
; 
 811     kr 
= IOConnectCallMethod(conn
, kAppleFDEKeyStore_setStashKey
, 
 813                              &inStruct2
, sizeof(inStruct2
), 
 817     if  (kr 
== KERN_SUCCESS
) { 
 818         service_kb_stash_create(context
, keydata
, (unsigned)keydata_len
); 
 828 // Load the master stash key 
 830 OSStatus 
service_stash_load_key(service_context_t 
* context
, xpc_object_t event
, xpc_object_t reply
) 
 832     kern_return_t kr 
= KERN_SUCCESS
; 
 833     size_t keydata_len 
= 0; 
 835     const uint8_t *keydata 
= xpc_dictionary_get_data(event
, SERVICE_XPC_KEY
, &keydata_len
); 
 836     require(keydata
, done
); 
 838     kr 
= service_kb_stash_load(context
, keydata
, (cryptosize_t
) keydata_len
, true); 
 845 // Signal the AppleFDEKeyStore to take the tagged FDE key 
 846 // and keychain master key, stash them in an encrypted 
 847 // blob structure and write the blob to NVRAM.  The random 
 848 // encryption key is written to the SMC. 
 851 OSStatus 
service_stash_blob(xpc_object_t event
, xpc_object_t reply
) 
 853     kern_return_t kr 
= KERN_INVALID_ARGUMENT
; 
 855     io_connect_t conn 
= openiodev(); 
 858     kr 
= IOConnectCallMethod(conn
, kAppleFDEKeyStore_commitStash
, 
 871 bool peer_has_entitlement(xpc_connection_t peer
, const char * entitlement
) 
 873     bool entitled 
= false; 
 875     xpc_object_t value 
= xpc_connection_copy_entitlement_value(peer
, entitlement
); 
 876     if (value 
&& (xpc_get_type(value
) == XPC_TYPE_BOOL
)) { 
 877         entitled 
= xpc_bool_get_value(value
); 
 880     if (value
) xpc_release(value
); 
 884 static char * sel_to_char(uint64_t sel
) 
 887         case SERVICE_STASH_SET_KEY
: 
 889         case SERVICE_STASH_GET_KEY
: 
 891         case SERVICE_STASH_BLOB
: 
 893         case SERVICE_KB_LOAD
: 
 895         case SERVICE_KB_SAVE
: 
 897         case SERVICE_KB_UNLOCK
: 
 899         case SERVICE_KB_LOCK
: 
 901         case SERVICE_KB_CHANGE_SECRET
: 
 902             return "kb_change_secret"; 
 903         case SERVICE_KB_CREATE
: 
 905         case SERVICE_KB_IS_LOCKED
: 
 906             return "kb_is_locked"; 
 907         case SERVICE_KB_RESET
: 
 909         case SERVICE_KB_UNLOAD
: 
 911         case SERVICE_KB_LOAD_UID
: 
 912             return "kb_load_uid"; 
 918 static char * err_to_char(int err
) 
 923         case KB_GeneralError
: 
 924             return "general error"; 
 926             return "bag not found"; 
 929         case KB_BagNotLoaded
: 
 930             return "bag not loaded"; 
 933         case KB_InvalidSession
: 
 934             return "invalid session"; 
 940 void service_peer_event_handler(xpc_connection_t connection
, xpc_object_t event
) 
 942     xpc_type_t type 
= xpc_get_type(event
); 
 945     if (type 
== XPC_TYPE_ERROR
) { 
 946                 if (event 
== XPC_ERROR_CONNECTION_INVALID
) { 
 949         assert(type 
== XPC_TYPE_DICTIONARY
); 
 951         int rc 
= KB_GeneralError
; 
 952         uint64_t request 
= 0; 
 953         const uint8_t * secret 
= NULL
, * new_secret 
= NULL
; 
 954         size_t secret_len 
= 0, new_secret_len 
= 0, data_len 
= 0; 
 955         service_context_t 
* context 
= NULL
; 
 956         bool free_context 
= false; 
 958         const char *entitlement
; 
 960         xpc_object_t reply 
= xpc_dictionary_create_reply(event
); 
 962         request 
= xpc_dictionary_get_uint64(event
, SERVICE_XPC_REQUEST
); 
 965         // For SERVICE_KB_{UNLOAD,LOAD} only, allow non-securityd, non-root but 
 967         if (request 
== SERVICE_KB_UNLOAD 
|| request 
== SERVICE_KB_LOAD_UID
) { 
 969                 case SERVICE_KB_UNLOAD
: 
 970                     entitlement 
= "com.apple.private.securityd.keybag-unload"; 
 972                 case SERVICE_KB_LOAD_UID
: 
 973                     entitlement 
= "com.apple.private.securityd.keybag-load"; 
 976             if (!peer_has_entitlement(connection
, entitlement
) && !peer_has_entitlement(connection
, "com.apple.keystore.device")) { 
 977                 xpc_connection_cancel(connection
); 
 981             if (xpc_connection_get_euid(connection
) != 0) { 
 982                 xpc_connection_cancel(connection
); 
 985             if (!check_signature(connection
)) { 
 986                 xpc_connection_cancel(connection
); 
 991         data 
= xpc_dictionary_get_data(event
, SERVICE_XPC_CONTEXT
, &data_len
); 
 992         require_action(data 
|| request 
== SERVICE_KB_UNLOAD 
|| request 
== SERVICE_KB_LOAD_UID
, done
, rc 
= KB_GeneralError
); 
 994             require(data_len 
== sizeof(service_context_t
), done
); 
 995             context 
= (service_context_t
*)data
; 
 997             audit_token_t audit_token 
= { 0 }; 
 998             xpc_connection_get_audit_token(connection
, &audit_token
); 
 999             context 
= calloc(1, sizeof(service_context_t
)); 
1000             context
->s_id 
= xpc_connection_get_asid(connection
); 
1001             context
->s_uid 
= xpc_connection_get_euid(connection
); 
1002             context
->procToken 
= audit_token
; 
1003             free_context 
= true; 
1006         require_action(context
->s_id 
!= AU_DEFAUDITSID
, done
, rc 
= KB_InvalidSession
); 
1007         require_action(context
->s_uid 
!= AU_DEFAUDITID
, done
, rc 
= KB_InvalidSession
); // we only want to work in actual user sessions. 
1010             case SERVICE_KB_CREATE
: 
1011                 //                if (kb_service_has_entitlement(peer, "com.apple.keystore.device")) { 
1012                 secret 
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET
, &secret_len
); 
1013                 rc 
= service_kb_create(context
, secret
, (int)secret_len
); 
1016             case SERVICE_KB_LOAD
: 
1017                 rc 
= service_kb_load(context
); 
1019             case SERVICE_KB_UNLOAD
: 
1020                 rc 
= service_kb_unload(context
); 
1022             case SERVICE_KB_SAVE
: 
1023                 rc 
= service_kb_save(context
); 
1025             case SERVICE_KB_UNLOCK
: 
1026                 secret 
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET
, &secret_len
); 
1027                 rc 
= service_kb_unlock(context
, secret
, (int)secret_len
); 
1029             case SERVICE_KB_LOCK
: 
1030                 rc 
= service_kb_lock(context
); 
1032             case SERVICE_KB_CHANGE_SECRET
: 
1033                 secret 
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET
, &secret_len
); 
1034                 new_secret 
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET_NEW
, &new_secret_len
); 
1035                 rc 
= service_kb_change_secret(context
, secret
, (int)secret_len
, new_secret
, (int)new_secret_len
); 
1037             case SERVICE_KB_RESET
: 
1038                 secret 
= xpc_dictionary_get_data(event
, SERVICE_XPC_SECRET
, &secret_len
); 
1039                 rc 
= service_kb_reset(context
, secret
, (int)secret_len
); 
1041             case SERVICE_KB_IS_LOCKED
: 
1042                 rc 
= service_kb_is_locked(context
, reply
); 
1044             case SERVICE_STASH_GET_KEY
: 
1045                 rc 
= service_stash_get_key(context
, event
, reply
); 
1047             case SERVICE_STASH_SET_KEY
: 
1048                 rc 
= service_stash_set_key(context
, event
, reply
); 
1050             case SERVICE_STASH_LOAD_KEY
: 
1051                 rc 
= service_stash_load_key(context
, event
, reply
); 
1053             case SERVICE_KB_LOAD_UID
: 
1054                 uid 
= (uid_t
)xpc_dictionary_get_uint64(event
, SERVICE_XPC_UID
); 
1055                 rc 
= service_kb_load_uid(uid
); 
1058             case SERVICE_STASH_BLOB
: 
1059                 rc 
= service_stash_blob(event
, reply
); 
1063                 LOG("unknown service type"); 
1069         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); 
1072             syslog(LOG_NOTICE
, "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); 
1075         xpc_dictionary_set_int64(reply
, SERVICE_XPC_RC
, rc
); 
1076         xpc_connection_send_message(connection
, reply
); 
1084 bool check_signature(xpc_connection_t connection
) 
1086 #if !(DEBUG || RC_BUILDIT_YES) 
1087     audit_token_t token
; 
1089     xpc_connection_get_audit_token(connection
, &token
); 
1091     SecTaskRef task 
= SecTaskCreateWithAuditToken(NULL
, token
); 
1093         syslog(LOG_NOTICE
, "failed getting SecTaskRef of the client"); 
1097     uint32_t flags 
= SecTaskGetCodeSignStatus(task
); 
1098     /* check if valid and platform binary, but not platform path */ 
1099     if ((flags 
& (CS_VALID 
| CS_PLATFORM_BINARY 
| CS_PLATFORM_PATH
)) != (CS_VALID 
| CS_PLATFORM_BINARY
)) { 
1100         syslog(LOG_NOTICE
, "client is not a platform binary: %0x08x", flags
); 
1105     CFStringRef signingIdentity 
= SecTaskCopySigningIdentifier(task
, NULL
); 
1107     if (signingIdentity 
== NULL
) { 
1108         syslog(LOG_NOTICE
, "client have no code sign identity"); 
1112     bool res 
= CFEqual(signingIdentity
, CFSTR("com.apple.securityd")); 
1113     CFRelease(signingIdentity
); 
1116         syslog(LOG_NOTICE
, "client is not not securityd"); 
1124 static void register_for_notifications() 
1126     __block kern_return_t kr
; 
1127     static mach_port_t mp 
= MACH_PORT_NULL
; 
1129     static dispatch_once_t onceToken 
= 0; 
1130     dispatch_once(&onceToken
, ^{ 
1131         kr 
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &mp
); 
1132         if (kr 
== KERN_SUCCESS
) { 
1133             dispatch_source_t mach_src 
= dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV
, mp
, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0)); 
1134             dispatch_source_set_event_handler(mach_src
, ^{ 
1135                 mach_msg_return_t mr
; 
1136                 uint8_t buf
[sizeof(aks_notification_msg_t
) + MAX_TRAILER_SIZE
] = {}; 
1137                 aks_notification_msg_t 
* msg 
= (aks_notification_msg_t
*)buf
; 
1138                 mr 
= mach_msg((mach_msg_header_t
*)&buf
, MACH_RCV_MSG
, 0, sizeof(buf
), mp
, MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
); 
1139                 if (mr 
== MACH_MSG_SUCCESS 
&& msg
->hdr
.msgh_id 
== AKS_NOTIFICATION_MSGID
) { 
1141                 } else if (mr 
== MACH_MSG_SUCCESS 
&& msg
->hdr
.msgh_id 
== AKS_NOTIFICATION_WRITE_SYSTEM_KEYBAG
) { 
1142                     syslog(LOG_NOTICE
, "request to update handle %d", msg
->handle
); 
1143                     update_keybag_handle(msg
->handle
); 
1145                     syslog(LOG_ERR
, "mach_msg error: %x", mr
); 
1148             dispatch_resume(mach_src
); 
1150             syslog(LOG_NOTICE
, "failed to create notification port"); 
1155     kr 
= aks_register_for_notifications(mp
, AKS_NOTIFICATION_WRITE_SYSTEM_KEYBAG
); 
1156     if (kr 
== KERN_SUCCESS
) { 
1157         syslog(LOG_NOTICE
, "registered for notifications"); 
1159         syslog(LOG_NOTICE
, "failed to register for notifications %d", kr
); 
1163 int main(int argc
, const char * argv
[]) 
1166     if (sandbox_init(SECURITYD_SERVICE_NAME
, SANDBOX_NAMED
, &errorbuf
) != 0) { 
1167         syslog(LOG_ERR
, "sandbox_init failed %s", errorbuf
); 
1168         sandbox_free_error(errorbuf
); 
1174     register_for_notifications(); 
1176     xpc_connection_t listener 
= xpc_connection_create_mach_service(SECURITYD_SERVICE_NAME
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
); 
1177     xpc_connection_set_event_handler(listener
, ^(xpc_object_t peer
) { 
1178         // It is safe to cast 'peer' to xpc_connection_t assuming 
1179         // we have a correct configuration in our launchd.plist. 
1180         xpc_connection_set_event_handler(peer
, ^(xpc_object_t event
) { 
1181             vproc_transaction_t transaction 
= vproc_transaction_begin(NULL
); 
1182             service_peer_event_handler(peer
, event
); 
1183             vproc_transaction_end(NULL
, transaction
); 
1185         xpc_connection_resume(peer
); 
1187     xpc_connection_resume(listener
);