1/* 2 * @APPLE_LICENSE_HEADER_START@ 3 * 4 * Copyright (c) 2010 Apple Computer, Inc. All Rights Reserved. 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25#define DEBUG_SECURE_PROMPT 0 26#if DEBUG_SECURE_PROMPT 27# define DEBUG_ASSERT_PRODUCTION_CODE 0 28# define DEBUG_ASSERT_COMPONENT_NAME_STRING "IOHIDSecurePromptClient" 29#endif 30 31#include <AssertMacros.h> 32#include <IOKit/IOLib.h> 33#include <sys/proc.h> 34#include <IOKit/IOCommandGate.h> 35#include <IOKit/hidsystem/IOHIKeyboardMapper.h> 36#include <IOKit/crypto/AppleFDEKeyStore.h> 37#include <uuid/uuid.h> 38#include "IOHIDSecurePromptClient.h" 39 40/******************************************************************************/ 41/* Helper functions 42 */ 43static void __EraseData(OSData *target); 44static void __EraseDataArray(OSArray *target); 45static void __EraseMemory(void *mem, UInt32 size); 46static void __InsertBytes(void *dest, UInt32 insertPoint, UInt32 destCount, void *source, UInt32 sourceCount, UInt32 size); 47 48/******************************************************************************/ 49/* Through the course of this file, the word hash is used to mean a cryprographically 50 secure one way hash 51 */ 52extern unsigned int hid_adb_2_usb_keymap[]; //In Cosmo_USB2ADB.cpp 53 54#undef super 55#define super IOUserClient 56 57OSDefineMetaClassAndStructors(IOHIDSecurePromptClient, IOUserClient) 58 59/******************************************************************************/ 60/* The IOHIDSecurePromptClient_RawKeystrokeData stores raw keycodes for use later 61 if we need to generate a new set of UTF32Chars for comparison. 62 */ 63typedef struct IOHIDSecurePromptClient_RawKeystrokeData { 64 UInt8 modifier[4]; 65 UInt8 code[4]; 66} IOHIDSecurePromptClient_RawKeystrokeData; 67 68#ifndef UTF32Char 69 typedef UInt32 UTF32Char; 70#endif 71 72/* The keyqueue message is sent to the subscribee letting them know that a new 73 keystroke has been queued up. 74 */ 75typedef struct IOHIDSecurePromptClient_KeyqueueMessage { 76 mach_msg_header_t message; 77 mach_msg_body_t body; 78 UInt32 id; 79} IOHIDSecurePromptClient_KeyqueueMessage; 80 81/* The keyqueue entry stores the correspondence between the id sent via the 82 keyqueue message and the actual keycode delivered. 83 */ 84typedef struct IOHIDSecurePromptClient_KeyqueueEntry { 85 UInt16 id; 86 UInt8 modifier; 87 UInt8 code; 88} IOHIDSecurePromptClient_KeyqueueEntry; 89 90/* The IOHIDSecurePromptClient_ExpansionData structure stores all of the instance data for 91 the IOHIDSecurePromptClient class. 92 */ 93typedef struct IOHIDSecurePromptClient_ExpansionData { 94 UInt8 gathering; // Are we currently gathering keystrokes? 95 UInt8 dead; // Has this client been closed or abandoned? 96 UInt8 uuidState; // See kUUIDState* below 97 UInt16 nextQueueID; // Used to keyqueue ids above 98 UInt16 insertionPoint; // The insertion point for new characters 99 UInt16 stringLength; // Valid data length in the unicode and raw keystroke buffers 100 UInt16 bufferLength; // Maximum size of the unicode and raw keystroke buffers 101 UInt32 layout; // The keyboard layout used for code ->> value translation 102 OSData *layouts; // All of the keyboard layouts 103 // probably won't be an OSData in the end 104 IONotifier *keyboardNotifier; // This is the notifier set up by the instantiating class 105 // the client is responsible for releasing it. 106 mach_port_t port; // The notification port supplied by the client user 107 UTF32Char *unicode; // This is a buffer of UTF32Char's 108 IOHIDSecurePromptClient_RawKeystrokeData 109 *rawKeystrokes; // This is a buffer of IOHIDSecurePromptClient_RawKeystrokeData's 110 OSArray *messageQueue; // A queue of all of the key ids that have been sent out but not yet gotten back 111 uuid_t uuid; // The uuid is used to idetify the password in the keystore. Therefore, if two 112 // clients have the same uuid, they identify the same password. Care must be taken 113 // so that two clients do not *modify* the same password, however. That would be bad. 114 // This is the reason for uuidState above and kUUIDState* below. 115 IOCommandGate *gate; // The command gate used to serialize data coming from all 116 // of the keyboards and the client user. 117 kbdBitVector keyState; // A bitvector to store the key state information 118 IOByteCount keyStateSize; // The size of said bitvector 119 120} IOHIDSecurePromptClient_ExpansionData; 121 122enum { 123 kUUIDStateNeverSaved, // client has no coresponding keystore entry 124 kUUIDStateIsDirty, // client has a keystore entry, but it is not in sync with internal data 125 kUUIDStateIsClean, // client and keystore are in sync 126 kUUIDStateIsGhost // client ghosts a keystore entry. It cannot gather new data. 127}; 128enum { 129 kControlModifier = 0x1, 130 kShiftModifier = 0x2, 131 kOptionModifier = 0x4, 132 kCommandModifier = 0x8 133}; 134 135 136 137 138/******************************************************************************/ 139bool 140IOHIDSecurePromptClient::initWithTask(task_t owningTask, 141 void* security_id, 142 UInt32 type, 143 OSDictionary * properties) 144{ 145 require(super::initWithTask(owningTask, security_id, type), init_error); 146 147 _reserved = (IOHIDSecurePromptClient_ExpansionData*)IOMalloc(sizeof(IOHIDSecurePromptClient_ExpansionData)); 148 require(_reserved, init_error); 149 150 bzero(_reserved, sizeof(IOHIDSecurePromptClient_ExpansionData)); 151 152 // initially we allow for a 32 character password but will grow it if needed 153 require_noerr(ensureBufferSize(32), init_error); 154 155 _reserved->messageQueue = OSArray::withCapacity(4); 156 require(_reserved->messageQueue, init_error); 157 158 _reserved->keyStateSize = 4*((NX_NUMKEYCODES+(EVK_BITS_PER_UNIT-1))/EVK_BITS_PER_UNIT); 159 _reserved->keyState = (kbdBitVector) IOMalloc(_reserved->keyStateSize); 160 bzero(_reserved->keyState, _reserved->keyStateSize); 161 require(_reserved->keyState, init_error); 162 uuid_generate(_reserved->uuid); 163 164#if DEBUG_SECURE_PROMPT 165#warning remove 166 uuid_string_t string; 167 uuid_unparse(_reserved->uuid, string); 168 IOLog("%s made UUID %s\n", __func__, string); 169#endif 170 171 _reserved->uuidState = kUUIDStateNeverSaved; 172 173// vtn3 TODO: setup layouts 174 175 return super::initWithTask(owningTask, security_id, type, properties); 176 177init_error: 178 releaseReserved(); 179 return false; 180} 181 182/******************************************************************************/ 183bool 184IOHIDSecurePromptClient::start(IOService * provider) 185{ 186 if (!_reserved->gate) { 187 IOWorkLoop *loop = provider->getWorkLoop(); 188 require(loop, start_error); 189 190 _reserved->gate = IOCommandGate::commandGate(this); 191 require(_reserved->gate, start_error); 192 193 require(kIOReturnSuccess == loop->addEventSource(_reserved->gate), start_error); 194 } 195 196 require(valid(), start_error); 197 198 return super::start(provider); 199 200start_error: 201 return false; 202} 203 204/******************************************************************************/ 205void 206IOHIDSecurePromptClient::releaseReserved() 207{ 208 if (_reserved) { 209 if (_reserved->gate) { 210 _reserved->gate->release(); 211 _reserved->gate = NULL; 212 } 213 if (_reserved->layouts) { 214 _reserved->layouts->release(); 215 _reserved->layouts = NULL; 216 } 217 218 ensureBufferSize(0); // special case erase 219 220 if (_reserved->keyboardNotifier) { 221 _reserved->keyboardNotifier->remove(); 222 _reserved->keyboardNotifier = NULL; 223 } 224 if (_reserved->keyState) { 225 IOFree( _reserved->keyState, _reserved->keyStateSize); 226 _reserved->keyState = NULL; 227 _reserved->keyStateSize = 0; 228 } 229 IOFree(_reserved, sizeof(IOHIDSecurePromptClient_ExpansionData)); 230 _reserved = NULL; 231 } 232} 233 234/******************************************************************************/ 235void 236IOHIDSecurePromptClient::free() 237{ 238 sync(); 239 releaseReserved(); 240 super::free(); 241} 242 243/******************************************************************************/ 244bool 245IOHIDSecurePromptClient::gathering() 246{ 247 require(valid(), uninitialized_data); 248 return _reserved->gathering; 249 250uninitialized_data: 251 return false; 252} 253 254/******************************************************************************/ 255bool 256IOHIDSecurePromptClient::dead() 257{ 258 require(_reserved, uninitialized_data); 259 return _reserved->dead; 260 261uninitialized_data: 262 return true; 263} 264 265/******************************************************************************/ 266void 267IOHIDSecurePromptClient::setNotifier(IONotifier *notifier) 268{ 269 require(valid(), exit_early); 270 if (_reserved->keyboardNotifier) 271 _reserved->keyboardNotifier->remove(); 272 273 _reserved->keyboardNotifier = notifier; 274 if (notifier) 275 notifier->retain(); 276 277exit_early: 278 ; 279} 280 281/******************************************************************************/ 282IOReturn 283IOHIDSecurePromptClient::postKey(UInt32 key, 284 bool down) 285{ 286 uintptr_t p1 = key; 287 uintptr_t p2 = down; 288 require(valid(), uninitialized_data); 289 return _reserved->gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, 290 this, 291 &IOHIDSecurePromptClient::postKeyGated), 292 (void*)p1, (void*)p2); 293uninitialized_data: 294 return kIOReturnInternalError; 295} 296 297/******************************************************************************/ 298/* There is some debate about using the HID keys or the old ADB keys that come 299 into the function. Everything that comes in right now will be goes from HID 300 to ADB and back to HID. 301 */ 302IOReturn 303IOHIDSecurePromptClient::postKeyGated(void * p1, void * p2, void *, void *) 304{ 305 UInt32 key = (uintptr_t)p1; 306 bool down = (uintptr_t)p2; 307 bool keep = false; 308 bool wasDown = false; 309 UInt8 hidCode = key < 0x80 ? hid_adb_2_usb_keymap[key] : 0xff; 310 IOReturn result = kIOReturnInternalError; 311 312 if (dead()) { 313 return kIOReturnNotOpen; 314 } 315 if (!gathering()) { 316 return kIOReturnNotReady; 317 } 318 require(valid(), finished); 319 320 result = kIOReturnBadArgument; 321 require(key < 0xff, finished); 322 323 wasDown = EVK_IS_KEYDOWN(key, _reserved->keyState); 324 325 // record all presses, even if we don't suppress them 326 if (down) { 327 if (!wasDown) { 328 EVK_KEYDOWN(key, _reserved->keyState); 329 } 330 } 331 else { 332 if (wasDown) { 333 EVK_KEYUP(key, _reserved->keyState); 334 } 335 // suppress ups 336 result = kIOReturnSuccess; 337 goto finished; 338 } 339 340 if (modifierDown(kControlModifier | kCommandModifier)) { 341 // control or command and we don't use it 342 goto finished; 343 } 344 345 if ((hidCode >= 0x04) && (hidCode <= 0x27)) // a-z, 0-9 346 keep = true; 347 if ((hidCode >= 0x2c) && (hidCode <= 0x38)) // space, [, ], etc. 348 keep = true; 349 if ((hidCode >= 0x54) && (hidCode <= 0x63)) // most keypad 350 keep = true; 351 if ((hidCode >= 0x85) && (hidCode <= 0x86)) // keypad comma, = 352 keep = true; 353 354 if (keep && down && !wasDown) { 355 // This will suppress all repeats and multiple keypresses 356 queueMessage(key); 357 // The secure client has claimed this key for its own. Suppress. 358 result = kIOReturnSuccess; 359 } 360 else { 361 // this is a key that we do not want to suppress. 362 } 363 364finished: 365 return result; 366} 367 368/******************************************************************************/ 369void 370IOHIDSecurePromptClient::queueMessage(UInt8 code) 371{ 372 require(valid(), uninitialized_data); 373 // This block is for scoping purposes only. 374 { 375 // set up all the data structures 376 UInt8 modifier = modifierState(); 377 UInt16 id = _reserved->nextQueueID++; 378 IOHIDSecurePromptClient_KeyqueueEntry entry = { 379 id, 380 modifier, 381 code 382 }; 383 IOHIDSecurePromptClient_KeyqueueMessage msg = { 384 { 385 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,0), 386 sizeof(IOHIDSecurePromptClient_KeyqueueMessage), 387 _reserved->port, 388 MACH_PORT_NULL, 389 0, 390 keyMessage 391 }, 392 { 393 0 394 }, 395 id 396 }; 397 398 // add the message to our internal queue 399 OSData *entryData = OSData::withBytes(&entry, sizeof(entry)); 400 require(entryData, out_of_memory); 401 _reserved->messageQueue->setObject(entryData); 402 entryData->release(); 403 404 // and finally send the message 405 kern_return_t ret = mach_msg_send_from_kernel(&msg.message, msg.message.msgh_size); 406 switch ( ret ) { 407 case MACH_MSG_SUCCESS: /* Message is posted */ 408 // good 409 break; 410 case MACH_SEND_TIMED_OUT: /* Already has a message posted */ 411 // bad 412 IOLog("%s: Unexpected response to mach_msg_send_from_kernel\n", __func__); 413 break; 414 default: /* Log the error */ 415 // ugly 416 IOLog("%s: Very unexpected response to mach_msg_send_from_kernel: 0x%08x\n", __func__, ret); 417 break; 418 } 419 } 420out_of_memory: 421uninitialized_data: 422 ; 423} 424 425/******************************************************************************/ 426IOReturn 427IOHIDSecurePromptClient::clientClose() 428{ 429 OSIterator *itr = NULL; 430 require(_reserved, uninitialized_data); 431 sync(); 432 _reserved->gathering = false; 433 _reserved->dead = true; 434 435 // notify all providers of the state change 436 itr = getProviderIterator(); 437 if (itr) { 438 bool done = false; 439 while (!done) { 440 OSObject *provider; 441 while (!done && (NULL != (provider = itr->getNextObject()))) { 442 IOService *parent = OSDynamicCast(IOService, provider); 443 detach(parent); 444 } 445 if (itr->isValid()) { 446 done = true; 447 } 448 else { 449 // we may end up sending the mseeage to the same provider twice. 450 // that should not cause any issues. 451 itr->reset(); 452 } 453 } 454 itr->release(); 455 } 456 457uninitialized_data: 458 return super::clientClose(); 459} 460 461/******************************************************************************/ 462IOReturn 463IOHIDSecurePromptClient::registerNotificationPort(mach_port_t port, 464 UInt32 type, 465 io_user_reference_t refCon) 466{ 467 require(valid(), uninitialized_data); 468 // A type of 1 was chosen for no particular reason. 469 if (type == 1) { 470 _reserved->port = port; 471 return kIOReturnSuccess; 472 } 473uninitialized_data: 474 return super::registerNotificationPort(port, type, refCon); 475} 476 477/******************************************************************************/ 478IOExternalMethod * 479IOHIDSecurePromptClient::getTargetAndMethodForIndex(IOService ** targetP, 480 UInt32 index) 481{ 482 static const IOExternalMethod methodTemplate[] = { 483 // 0: kIOHIDSecurePromptClient_setGatheringMethod 484 { NULL, (IOMethod)&IOHIDSecurePromptClient::setGatheringMethod, kIOUCScalarIScalarO, 1, 0 }, 485 // 1: kIOHIDSecurePromptClient_setLayoutMethod 486 { NULL, (IOMethod)&IOHIDSecurePromptClient::setLayoutMethod, kIOUCScalarIScalarO, 1, 0 }, 487 // 2: kIOHIDSecurePromptClient_confirmKeyMethod 488 { NULL, (IOMethod)&IOHIDSecurePromptClient::confirmKeyMethod, kIOUCScalarIScalarO, 1, 1 }, 489 // 3: kIOHIDSecurePromptClient_getGatheringMethod 490 { NULL, (IOMethod)&IOHIDSecurePromptClient::getGatheringMethod, kIOUCScalarIScalarO, 1, 0 }, 491 // 4: kIOHIDSecurePromptClient_deleteKeysMethod 492 { NULL, (IOMethod)&IOHIDSecurePromptClient::deleteKeysMethod, kIOUCScalarIScalarO, 2, 1 }, 493 // 5: kIOHIDSecurePromptClient_getLayoutMethod 494 { NULL, (IOMethod)&IOHIDSecurePromptClient::getLayoutMethod, kIOUCScalarIScalarO, 1, 0 }, 495 // 6: kIOHIDSecurePromptClient_getIdentifierMethod 496 { NULL, (IOMethod)&IOHIDSecurePromptClient::getIdentifierMethod, kIOUCScalarIScalarO, 0, 1 }, 497 // 7: kIOHIDSecurePromptClient_compareClientMethod 498 { NULL, (IOMethod)&IOHIDSecurePromptClient::compareClientMethod, kIOUCScalarIScalarO, 1, 0 }, 499 // 8: kIOHIDSecurePromptClient_setUUIDMethod 500 { NULL, (IOMethod)&IOHIDSecurePromptClient::setUUIDMethod, kIOUCStructIStructO, sizeof(uuid_t), 0 }, 501 // 9: kIOHIDSecurePromptClient_getUUIDMethod 502 { NULL, (IOMethod)&IOHIDSecurePromptClient::getUUIDMethod, kIOUCStructIStructO, 0, sizeof(uuid_t) }, 503 // 10: kIOHIDSecurePromptClient_getInsertionPoint 504 { NULL, (IOMethod)&IOHIDSecurePromptClient::getInsertionPointMethod, kIOUCScalarIScalarO, 0, 1 }, 505 // 11: kIOHIDSecurePromptClient_setInsertionPoint 506 { NULL, (IOMethod)&IOHIDSecurePromptClient::setInsertionPointMethod, kIOUCScalarIScalarO, 1, 0 }, 507 // 12: kIOHIDSecurePromptClient_injectString 508 { NULL, (IOMethod)&IOHIDSecurePromptClient::injectStringMethod, kIOUCStructIStructO, kIOUCVariableStructureSize, 0 }, 509 // 13: redacted 510 { NULL, NULL, 0, 0, 0 }, 511 }; 512 513 require(valid(), uninitialized_data); 514 require(index < (sizeof(methodTemplate) / sizeof(methodTemplate[0])), bad_argument); 515 516 *targetP = this; 517 return( (IOExternalMethod *)(methodTemplate + index) ); 518 519uninitialized_data: 520bad_argument: 521 return NULL; 522} 523 524/******************************************************************************/ 525IOReturn 526IOHIDSecurePromptClient::setGatheringMethod(void * p1, void * p2 __unused, void * p3 __unused, void * p4 __unused, void * p5 __unused, void * p6 __unused) 527{ 528 UInt32 state = (uintptr_t)p1; 529 return setGathering(state); 530} 531 532/******************************************************************************/ 533IOReturn 534IOHIDSecurePromptClient::setGathering(UInt32 state) 535{ 536 uintptr_t tempState = state ? true : false; 537 require(valid(), uninitialized_data); 538 require(_reserved->uuidState != kUUIDStateIsGhost, uninitialized_data); 539 540 if (gathering() != tempState) { 541 _reserved->gathering = tempState; 542 543 // notify all providers of the state change 544 OSIterator *itr = getProviderIterator(); 545 if (itr) { 546 bool done = false; 547 while (!done) { 548 OSObject *provider; 549 while (!done && (NULL != (provider = itr->getNextObject()))) { 550 IOService *parent = OSDynamicCast(IOService, provider); 551 parent->message(gatheringMessage, this, (void*)tempState); 552 } 553 if (itr->isValid()) { 554 done = true; 555 } 556 else { 557 // we may end up sending the mseeage to the same provider twice. 558 // that should not cause any issues. 559 itr->reset(); 560 } 561 } 562 itr->release(); 563 } 564 } 565 566// vtn3 TODO: release local modifier flags 567 568 // clear out any queued keystrokes 569 if (_reserved->messageQueue) { 570 __EraseDataArray(_reserved->messageQueue); 571 _reserved->messageQueue->release(); 572 } 573 _reserved->messageQueue = OSArray::withCapacity(4); 574 575 return kIOReturnSuccess; 576 577uninitialized_data: 578 return kIOReturnNotOpen; 579} 580 581/******************************************************************************/ 582IOReturn 583IOHIDSecurePromptClient::setLayoutMethod(void * p1, void * p2, void * p3, void * p4, void * p5 __unused, void * p6 __unused) 584{ 585 require(valid(), uninitialized_data); 586 return _reserved->gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, 587 this, 588 &IOHIDSecurePromptClient::setLayoutGated), 589 p1, p2, p3, p4); 590uninitialized_data: 591 return kIOReturnInternalError; 592} 593 594/******************************************************************************/ 595IOReturn 596IOHIDSecurePromptClient::setLayoutGated(void * p1, void * p2 __unused, void * p3 __unused, void * p4 __unused) 597{ 598 UInt32 layout = (uintptr_t)p1; 599 return setLayout(layout); 600} 601 602/******************************************************************************/ 603IOReturn 604IOHIDSecurePromptClient::setLayout(UInt32 layout) 605{ 606 require(valid(), uninitialized_data); 607 require(_reserved->uuidState != kUUIDStateIsGhost, uninitialized_data); 608 609 if (_reserved->uuidState == kUUIDStateIsClean) 610 _reserved->uuidState = kUUIDStateIsDirty; 611 612// vtn3 TODO: validate layout entry 613 614 _reserved->layout = layout; 615 616 // clear out any queued keystrokes 617 if (_reserved->messageQueue) { 618 __EraseDataArray(_reserved->messageQueue); 619 _reserved->messageQueue->release(); 620 } 621 _reserved->messageQueue = OSArray::withCapacity(4); 622 623 // vtn3 TODO: release local modifier flags 624 // vtn3 TODO: remap value queue 625 626 return kIOReturnSuccess; 627 628uninitialized_data: 629 return kIOReturnInternalError; 630} 631 632/******************************************************************************/ 633IOReturn 634IOHIDSecurePromptClient::confirmKeyMethod(void * p1, void * p2, void * p3, void * p4, void * p5 __unused, void * p6 __unused) 635{ 636 require(valid(), uninitialized_data); 637 return _reserved->gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, 638 this, 639 &IOHIDSecurePromptClient::confirmKeyGated), 640 p1, p2, p3, p4); 641uninitialized_data: 642 return kIOReturnInternalError; 643} 644 645/******************************************************************************/ 646IOReturn 647IOHIDSecurePromptClient::confirmKeyGated(void * p1, void * p2, void * /* p3 */, void * /* p4 */) 648{ 649 UInt32 id = (uintptr_t)p1; 650 return confirmKey(id, (UInt32*)p2); 651} 652 653/******************************************************************************/ 654IOReturn 655IOHIDSecurePromptClient::confirmKey(UInt32 id, 656 UInt32 *count) 657{ 658 unsigned int index = 0; 659 IOReturn result = kIOReturnBadArgument; 660 OSCollectionIterator *iterator = NULL; 661 662 require(valid(), uninitialized_data); 663 require(_reserved->uuidState != kUUIDStateIsGhost, uninitialized_data); 664 result = kIOReturnInternalError; 665 require(count, invalid_argument); 666 result = kIOReturnBadMessageID; 667 668 // Search through the queue for the supplied ID 669 iterator = OSCollectionIterator::withCollection(_reserved->messageQueue); 670 require(iterator, finished); 671 do { 672 OSObject * obj = iterator->getNextObject(); 673 if (!obj) { 674 if (iterator->isValid()) { 675 goto finished; 676 } 677 else { 678 iterator->reset(); 679 } 680 } 681 else { 682 OSData *entryData = OSDynamicCast(OSData, obj); 683 IOHIDSecurePromptClient_KeyqueueEntry *entry = NULL; 684 if (entryData == NULL) { 685 IOLog("%s: Found bad index in messageQueue: %d\n", __func__, index); 686 continue; 687 } 688 entry = (IOHIDSecurePromptClient_KeyqueueEntry*)entryData->getBytesNoCopy(); 689 if (entry->id == id) { 690 // We have a match. Append it and remove it from the queue. 691 result = appendConfirmedKeyCode(entry->modifier, entry->code); 692 __EraseData(entryData); 693 _reserved->messageQueue->removeObject(index); 694 695 // Now set the return count 696 *count = _reserved->stringLength; 697 goto finished; 698 } 699 } 700 } 701 while (true); 702 703finished: 704invalid_argument: 705uninitialized_data: 706 if (iterator) 707 iterator->release(); 708 709 return result; 710} 711 712/******************************************************************************/ 713IOReturn 714IOHIDSecurePromptClient::appendConfirmedKeyCode(UInt8 modifier, 715 UInt8 code) 716{ 717 // Remap the zero key (a) to be an invalid key code 718 IOReturn result = kIOReturnInternalError; 719 UInt8 newCode = code ? code : 0xff; 720 IOHIDSecurePromptClient_RawKeystrokeData newKeystroke = {{ modifier }, { newCode }}; 721 722 // vtn3 TODO: get real value here. 723 UTF32Char newUnicode = (modifier << 16) | newCode; 724 require(valid(), exit_early); 725 726 if (_reserved->uuidState == kUUIDStateIsClean) 727 _reserved->uuidState = kUUIDStateIsDirty; 728 729 // vtn3 TODO: do something intelegent here. 730 // if there is a previous key code 731 // if it combines 732 // replace the old entry 733 // otherwise 734 { 735 // append the new entry 736 result = kIOReturnNoMemory; 737 require_noerr(ensureBufferSize(_reserved->stringLength + 1), exit_early); 738 __InsertBytes(_reserved->unicode, _reserved->insertionPoint, _reserved->stringLength, &newUnicode, 1, sizeof(newUnicode)); 739 __InsertBytes(_reserved->rawKeystrokes, _reserved->insertionPoint, _reserved->stringLength, &newKeystroke, 1, sizeof(newKeystroke)); 740 __EraseMemory(&newKeystroke, sizeof(newKeystroke)); 741 __EraseMemory(&newUnicode, sizeof(newUnicode)); 742 _reserved->insertionPoint++; 743 _reserved->stringLength++; 744 //IOLog("%s insertionPoint = %d; stringLength = %d; bufferLength = %d\n", __func__, _reserved->insertionPoint, _reserved->stringLength, _reserved->bufferLength); 745 } 746 result = kIOReturnSuccess; 747 748exit_early: 749 return result; 750} 751 752/******************************************************************************/ 753IOReturn 754IOHIDSecurePromptClient::deleteKeysMethod(void * p1, void * p2, void * p3, void * p4, void * p5 __unused, void * p6 __unused) 755{ 756 require(valid(), uninitialized_data); 757 return _reserved->gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, 758 this, 759 &IOHIDSecurePromptClient::deleteKeysGated), 760 p1, p2, p3, p4); 761uninitialized_data: 762 return kIOReturnInternalError; 763} 764 765/******************************************************************************/ 766IOReturn 767IOHIDSecurePromptClient::deleteKeysGated(void * p1, void * p2, void * p3, void * p4 __unused) 768{ 769 UInt32 length; 770 IOReturn result; 771 require(p3, invalid_argument); 772 result = deleteKeys((intptr_t)p1, (uintptr_t)p2, &length); 773 *(UInt64*)p3 = length; 774 return result; 775 776invalid_argument: 777 return kIOReturnBadArgument; 778} 779 780/******************************************************************************/ 781IOReturn 782IOHIDSecurePromptClient::deleteKeys(SInt32 index, 783 UInt32 count, 784 UInt32 *newLength) 785{ 786 require(valid(), uninitialized_data); 787 require(_reserved->uuidState != kUUIDStateIsGhost, uninitialized_data); 788 { 789 SInt32 deleteBegin = index; 790 791 // in case of early return, make sure newLength returns the length 792 *newLength = _reserved->stringLength; 793 794 if ((count == 0) || (_reserved->stringLength == 0)) { 795 // this is a valid exit early case 796 return kIOReturnSuccess; 797 } 798 799 if (deleteBegin < 0) { 800 // delete from the end 801 deleteBegin = _reserved->stringLength - count; 802 if (deleteBegin < 0) 803 deleteBegin = 0; 804 } 805 require(_reserved->stringLength > (unsigned)deleteBegin, overrun); 806 807 if (((SInt64)count) > _reserved->stringLength - deleteBegin) { 808 count = _reserved->stringLength - deleteBegin; 809 } 810 811 memmove(_reserved->unicode + deleteBegin, 812 _reserved->unicode + (deleteBegin + count), 813 (_reserved->stringLength - deleteBegin - count) * sizeof(UTF32Char)); 814 memmove(_reserved->rawKeystrokes + deleteBegin, 815 _reserved->rawKeystrokes + (deleteBegin + count), 816 (_reserved->stringLength - deleteBegin - count) * sizeof(IOHIDSecurePromptClient_RawKeystrokeData)); 817 818 // note it is dirty 819 if (_reserved->uuidState == kUUIDStateIsClean) 820 _reserved->uuidState = kUUIDStateIsDirty; 821 822 _reserved->stringLength -= count; 823 *newLength = _reserved->stringLength; 824 825 // adjust insertion point 826 if (_reserved->insertionPoint > index) { 827 _reserved->insertionPoint -= count; 828 if (_reserved->insertionPoint < index) { 829 _reserved->insertionPoint = index; 830 } 831 } 832 833 //IOLog("%s insertionPoint = %d; stringLength = %d; bufferLength = %d\n", __func__, _reserved->insertionPoint, _reserved->stringLength, _reserved->bufferLength); 834 835 return kIOReturnSuccess; 836 } 837uninitialized_data: 838 return kIOReturnInternalError; 839overrun: 840 return kIOReturnOverrun; 841} 842 843/******************************************************************************/ 844bool 845IOHIDSecurePromptClient::valid() 846{ 847 require(_reserved, invalid); 848// vtn3 TODO: require layouts 849// require(_reserved->layouts, invalid); 850 nrequire(_reserved->dead, invalid); 851 require(_reserved->unicode, invalid); 852 require(_reserved->rawKeystrokes, invalid); 853 require(_reserved->messageQueue, invalid); 854 require(_reserved->gate, invalid); 855 require(_reserved->keyState, invalid); 856 require(_reserved->insertionPoint <= _reserved->stringLength, invalid); 857 858 return true; 859invalid: 860 return false; 861} 862 863/******************************************************************************/ 864#define CONTROL_DOWN(X) (EVK_IS_KEYDOWN(0x3b, X) || EVK_IS_KEYDOWN(0x3e, X)) // ADB Control keys 865#define SHIFT_DOWN(X) (EVK_IS_KEYDOWN(0x38, X) || EVK_IS_KEYDOWN(0x3c, X)) // ADB Shift keys 866#define OPTION_DOWN(X) (EVK_IS_KEYDOWN(0x3a, X) || EVK_IS_KEYDOWN(0x3d, X)) // ADB Alt keys 867#define COMMAND_DOWN(X) (EVK_IS_KEYDOWN(0x37, X) || EVK_IS_KEYDOWN(0x36, X)) // ADB GUI keys 868 869/******************************************************************************/ 870UInt8 871IOHIDSecurePromptClient::modifierState() 872{ 873 UInt8 result = (CONTROL_DOWN(_reserved->keyState) ? kControlModifier : 0) | 874 (SHIFT_DOWN(_reserved->keyState) ? kShiftModifier : 0) | 875 (OPTION_DOWN(_reserved->keyState) ? kOptionModifier : 0) | 876 (COMMAND_DOWN(_reserved->keyState) ? kCommandModifier : 0); 877 return result; 878} 879 880/******************************************************************************/ 881bool 882IOHIDSecurePromptClient::modifierDown(UInt8 modifierFlag) 883{ 884 bool result = (modifierState() & modifierFlag) ? true : false; 885 return result; 886} 887 888/******************************************************************************/ 889IOReturn 890IOHIDSecurePromptClient::getIdentifierMethod(void * p1, void * p2 __unused, void * p3 __unused, void * p4 __unused, void * p5 __unused, void * p6 __unused) 891{ 892 require(valid() && p1, uninitialized_data); 893 894 *(UInt64*)p1 = identifier(); 895 return kIOReturnSuccess; 896 897uninitialized_data: 898 return kIOReturnInternalError; 899} 900 901/******************************************************************************/ 902uint64_t 903IOHIDSecurePromptClient::identifier() 904{ 905 uint64_t result = 0xffffffff & (uint64_t)this; 906 return result; 907} 908 909/******************************************************************************/ 910IOReturn 911IOHIDSecurePromptClient::compareClientMethod(void * p1, void *, void *, void *, void *, void *) 912{ 913 // We deviate from our idiom above because we do not wish to hold both 914 // gates at the same time. Probably would not cause a problem, but it is possible, 915 OSData *tempData = NULL; 916 IOReturn result = kIOReturnInternalError; 917 uint64_t targetID = (uintptr_t)p1; 918 OSIterator *siblings = NULL; 919 IORegistryEntry *parent = NULL; 920 IOHIDSecurePromptClient *target = NULL; 921 uuid_t targetUUID; 922 uuid_t selfUUID; 923 UInt8 *targetBuffer = NULL; 924 UInt8 *selfBuffer = NULL; 925 uint32_t targetBufferSize; 926 uint32_t selfBufferSize; 927 928 require(valid(), uninitialized_data); 929 require(AppleFDEKeyStore::instance, uninitialized_data); 930 931 // find the target 932 parent = getParentEntry(gIOServicePlane); 933 require(parent, no_siblings); 934 siblings = parent->getChildIterator(gIOServicePlane); 935 require(siblings, no_siblings); 936 937 while(NULL != (target = nextForIterator(siblings))) { 938 if (target->identifier() == targetID) 939 break; 940 } 941 942 require(target, no_target); 943 require(target->valid(), no_target); 944 945 result = target->getUUIDMethod(targetUUID, NULL, NULL, NULL, NULL, NULL); 946 require(result == kIOReturnSuccess, no_target); 947 948 result = getUUIDMethod(selfUUID, NULL, NULL, NULL, NULL, NULL); 949 require(result == kIOReturnSuccess, no_target); 950 951 sync(); 952 target->sync(); 953 954#if DEBUG_SECURE_PROMPT 955#warning remove 956 uuid_string_t string; 957 uuid_unparse(selfUUID, string); 958 IOLog("%s of UUID %s to", __func__, string); 959 uuid_unparse(targetUUID, string); 960 IOLog(" UUID %s", string); 961#endif 962 963 targetBuffer = (UInt8*)IOMalloc(AKS_MAX_PASSPHRASE_SIZE); 964 selfBuffer = (UInt8*)IOMalloc(AKS_MAX_PASSPHRASE_SIZE); 965 require(targetBuffer && selfBuffer, out_of_memory); 966 967 // check the buffers 968 targetBufferSize = AKS_MAX_PASSPHRASE_SIZE; 969 result = AppleFDEKeyStore::instance->getPassphrase(targetUUID, targetBuffer, targetBufferSize, &targetBufferSize); 970 require(result == kIOReturnSuccess, keystore_error); 971 selfBufferSize = AKS_MAX_PASSPHRASE_SIZE; 972 result = AppleFDEKeyStore::instance->getPassphrase(selfUUID, selfBuffer, selfBufferSize, &selfBufferSize); 973 require(result == kIOReturnSuccess, keystore_error); 974 975 if ((targetBufferSize == selfBufferSize) && (0 == memcmp(targetBuffer, selfBuffer, targetBufferSize))) { 976 goto success; 977 } 978 979 // for each acceptable layout 980 // setLayout on self in gate to that layout 981 // sync 982 // check the buffers (see above) 983 984 // if you get here, you have failed 985 result = kIOReturnNotPrivileged; 986 987success: 988keystore_error: 989out_of_memory: 990 if (targetBuffer) { 991 __EraseMemory(targetBuffer, AKS_MAX_PASSPHRASE_SIZE); 992 IOFree(targetBuffer, AKS_MAX_PASSPHRASE_SIZE); 993 } 994 if (selfBuffer) { 995 __EraseMemory(selfBuffer, AKS_MAX_PASSPHRASE_SIZE); 996 IOFree(selfBuffer, AKS_MAX_PASSPHRASE_SIZE); 997 } 998 999no_target: 1000 if (siblings) { 1001 siblings->release(); 1002 } 1003 1004no_siblings: 1005 if (tempData) { 1006 __EraseData(tempData); 1007 tempData->release(); 1008 } 1009 1010uninitialized_data: 1011 return result; 1012} 1013 1014/******************************************************************************/ 1015IOReturn 1016IOHIDSecurePromptClient::getUUIDMethod(void * p1, void * p2 __unused, void * p3 __unused, void * p4 __unused, void * p5 __unused, void * p6 __unused) 1017{ 1018 return _reserved->gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, 1019 this, 1020 &IOHIDSecurePromptClient::getUUIDGated), 1021 p1, p2, p3, p4); 1022} 1023 1024/******************************************************************************/ 1025IOReturn 1026IOHIDSecurePromptClient::getUUIDGated(void * p1, void * p2 __unused, void * p3 __unused, void * p4 __unused) 1027{ 1028 UInt8 *data = (UInt8*)p1; 1029 1030 require(valid(), uninitialized_data); 1031 require(p1, uninitialized_data); 1032 1033 if (_reserved->uuidState == kUUIDStateNeverSaved) 1034 _reserved->uuidState = kUUIDStateIsDirty; 1035 1036 bcopy(_reserved->uuid, data, sizeof(uuid_t)); 1037 return kIOReturnSuccess; 1038 1039uninitialized_data: 1040 return kIOReturnInternalError; 1041} 1042 1043/******************************************************************************/ 1044IOReturn 1045IOHIDSecurePromptClient::setUUIDMethod(void * p1, void * p2, void * p3, void * p4, void * p5 __unused, void * p6 __unused) 1046{ 1047 return _reserved->gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, 1048 this, 1049 &IOHIDSecurePromptClient::setUUIDGated), 1050 p1, p2, p3, p4); 1051} 1052 1053/******************************************************************************/ 1054IOReturn 1055IOHIDSecurePromptClient::setUUIDGated(void * p1, void * p2 __unused, void * p3 __unused,void * p4 __unused) 1056{ 1057 require(valid(), uninitialized_data); 1058 require(p1, uninitialized_data); 1059 return setUUID((UInt8*)p1); 1060 1061uninitialized_data: 1062 return kIOReturnInternalError; 1063} 1064 1065/******************************************************************************/ 1066IOReturn 1067IOHIDSecurePromptClient::setUUID(UInt8* bytes_in) 1068{ 1069 IOReturn result = kIOReturnNoMemory; 1070 uint32_t bufferSize = AKS_MAX_PASSPHRASE_SIZE; 1071 1072 bcopy(bytes_in, _reserved->uuid, sizeof(uuid_t)); 1073 1074#if DEBUG_SECURE_PROMPT 1075#warning remove 1076 uuid_string_t string; 1077 uuid_unparse(_reserved->uuid, string); 1078 IOLog("%s set UUID to %s\n", __func__, string); 1079#endif 1080 1081 if (_reserved->uuidState != kUUIDStateIsGhost) { 1082 setGathering(0); 1083 _reserved->uuidState = kUUIDStateIsGhost; 1084 } 1085 1086 UInt8 *buffer = (UInt8*)IOMalloc(AKS_MAX_PASSPHRASE_SIZE); 1087 require(buffer, out_of_memory); 1088 1089 // check the UUIDs 1090 bufferSize = AKS_MAX_PASSPHRASE_SIZE; 1091 result = AppleFDEKeyStore::instance->getPassphrase(_reserved->uuid, buffer, bufferSize, &bufferSize); 1092 require(result == kIOReturnSuccess, bad_uuid); 1093 1094bad_uuid: 1095out_of_memory: 1096 if (buffer) { 1097 __EraseMemory(buffer, AKS_MAX_PASSPHRASE_SIZE); 1098 IOFree(buffer, AKS_MAX_PASSPHRASE_SIZE); 1099 } 1100 1101 return result; 1102} 1103 1104/******************************************************************************/ 1105IOReturn 1106IOHIDSecurePromptClient::getInsertionPointMethod(void * p1, void *, void *, void *, void *, void *) 1107{ 1108 require(valid() && p1, uninitialized_data); 1109 1110 *(uint64_t*)p1 = getInsertionPoint(); 1111 return kIOReturnSuccess; 1112 1113uninitialized_data: 1114 return kIOReturnInternalError; 1115} 1116 1117/******************************************************************************/ 1118uint64_t 1119IOHIDSecurePromptClient::getInsertionPoint() 1120{ 1121 return _reserved->insertionPoint; 1122} 1123 1124/******************************************************************************/ 1125IOReturn 1126IOHIDSecurePromptClient::setInsertionPointMethod(void * p1, void * p2, void * p3, 1127 void * p4, void * p5 __unused, void * p6 __unused) 1128{ 1129 return _reserved->gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, 1130 this, 1131 &IOHIDSecurePromptClient::setInsertionPointGated), 1132 p1, p2, p3, p4); 1133} 1134 1135/******************************************************************************/ 1136IOReturn 1137IOHIDSecurePromptClient::setInsertionPointGated(void * p1, void * p2 __unused, void * p3 __unused,void * p4 __unused) 1138{ 1139 IOReturn result = kIOReturnBadArgument; 1140 uintptr_t value = (uintptr_t)p1; 1141 1142 require(valid(), bad_argument); 1143 require(value < 0x0fff, bad_argument); // cannot set the insertion pointer past the 4000th character 1144 1145 if (value == 0) { 1146 _reserved->insertionPoint = 0; 1147 } 1148 else { 1149 if (value >= _reserved->stringLength) { 1150 _reserved->insertionPoint = _reserved->stringLength; 1151 } 1152 else { 1153 _reserved->insertionPoint = value; 1154 } 1155 } 1156 result = kIOReturnSuccess; 1157 1158bad_argument: 1159 return result; 1160} 1161 1162/******************************************************************************/ 1163IOReturn 1164IOHIDSecurePromptClient::injectStringMethod(void * p1, void * p2, void * p3, 1165 void * p4, void * p5 __unused, void * p6 __unused) 1166{ 1167 return _reserved->gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, 1168 this, 1169 &IOHIDSecurePromptClient::injectStringGated), 1170 p1, p2, p3, p4); 1171} 1172 1173/******************************************************************************/ 1174IOReturn 1175IOHIDSecurePromptClient::injectStringGated(void * p1, void * p2, void * p3 __unused,void * p4 __unused) 1176{ 1177 IOReturn result = kIOReturnBadArgument; 1178 IOHIDSecurePromptClient_RawKeystrokeData * dummyRawData = NULL; 1179 UTF32Char *string = (UTF32Char*)p1; 1180 intptr_t length = (intptr_t)p2 / sizeof(UTF32Char); 1181 vm_size_t dummyDataSize = length * sizeof(IOHIDSecurePromptClient_RawKeystrokeData); 1182 1183 require(valid(), bad_argument); 1184 require(p1, bad_argument); 1185 1186 require((length > 0) && (length < 0x0fff), bad_argument); // not going to insert more than 4000 characters 1187 1188 dummyRawData = (IOHIDSecurePromptClient_RawKeystrokeData*)IOMalloc(dummyDataSize); 1189 memset(dummyRawData, 0xff, dummyDataSize); 1190 1191 __InsertBytes(_reserved->rawKeystrokes, _reserved->insertionPoint, _reserved->stringLength, string, length, sizeof(UTF32Char)); 1192 __InsertBytes(_reserved->unicode, _reserved->insertionPoint, _reserved->stringLength, dummyRawData, length, sizeof(UTF32Char)); 1193 __EraseMemory(string, length * sizeof(UTF32Char)); 1194 _reserved->insertionPoint += length; 1195 result = kIOReturnSuccess; 1196 1197bad_argument: 1198 if (dummyRawData) 1199 IOFree(dummyRawData, dummyDataSize); 1200 return result; 1201} 1202 1203/******************************************************************************/ 1204IOReturn 1205IOHIDSecurePromptClient::getGatheringMethod(void * p1, void * p2 __unused, void * p3 __unused, void * p4 __unused, void * p5 __unused, void * p6 __unused) 1206{ 1207 require(valid(), uninitialized_data); 1208 require(p1, uninitialized_data); 1209 1210 *(UInt64*)p1 = gathering(); 1211 1212 return kIOReturnSuccess; 1213 1214uninitialized_data: 1215 *(UInt64*)p1 = false; 1216 1217 return kIOReturnInternalError; 1218} 1219 1220/******************************************************************************/ 1221void 1222IOHIDSecurePromptClient::sync() 1223{ 1224 if (_reserved && _reserved->gate && !_reserved->dead) 1225 _reserved->gate->runAction(OSMemberFunctionCast(IOCommandGate::Action, 1226 this, 1227 &IOHIDSecurePromptClient::syncGated), 1228 0, 0, 0, 0); 1229} 1230 1231/******************************************************************************/ 1232IOReturn 1233IOHIDSecurePromptClient::syncGated(void * p1 __unused, void * p2 __unused, void * p3 __unused,void * p4 __unused) 1234{ 1235 if (_reserved && (_reserved->uuidState == kUUIDStateIsDirty) && valid()) { 1236 IOReturn result; 1237 1238 // this will return an error if the passphrase does not exist. don't care. 1239 AppleFDEKeyStore::instance->deletePassphrase(_reserved->uuid); 1240 1241 if (_reserved->stringLength > 0) { 1242 result = AppleFDEKeyStore::instance->setPassphrase(_reserved->uuid, 1243 _reserved->unicode, 1244 _reserved->stringLength * sizeof(UTF32Char)); 1245 if (result != kIOReturnSuccess) 1246 IOLog("%s failed to setPassphrase for code: %08x\n", __func__, result); 1247 } 1248 1249 _reserved->uuidState = kUUIDStateIsClean; 1250 1251#if DEBUG_SECURE_PROMPT 1252#warning remove 1253 uuid_string_t string; 1254 uuid_unparse(_reserved->uuid, string); 1255 IOLog("%s on %s\n", __func__, string); 1256#endif 1257 } 1258 return kIOReturnSuccess; 1259} 1260 1261/******************************************************************************/ 1262IOReturn 1263IOHIDSecurePromptClient::getLayoutMethod(void * p1, void * p2 __unused, void * p3 __unused, void * p4 __unused, void * p5 __unused, void * p6 __unused) 1264{ 1265 require(valid(), uninitialized_data); 1266 require(p1, uninitialized_data); 1267 1268 *(UInt64*)p1 = _reserved->layout; 1269 1270 return kIOReturnSuccess; 1271 1272uninitialized_data: 1273 *(UInt64*)p1 = 0; 1274 1275 return kIOReturnInternalError; 1276} 1277 1278/******************************************************************************/ 1279IOHIDSecurePromptClient* 1280IOHIDSecurePromptClient::nextForIterator(OSIterator * iterator) 1281{ 1282 IOHIDSecurePromptClient *client = NULL; 1283 do { 1284 OSObject * obj = iterator->getNextObject(); 1285 if (!obj) { 1286 if (iterator->isValid()) { 1287 return NULL; 1288 } 1289 else { 1290 iterator->reset(); 1291 } 1292 } 1293 else { 1294 client = OSDynamicCast(IOHIDSecurePromptClient, obj); 1295 } 1296 } 1297 while (!client); 1298 1299 return client; 1300} 1301 1302/******************************************************************************/ 1303void 1304__EraseData(OSData *target) 1305{ 1306 if (target) { 1307 unsigned int size = target->getLength(); 1308 if (size) { 1309 void *bytes = (void*)target->getBytesNoCopy(); 1310 __EraseMemory(bytes, size); 1311 } 1312 } 1313} 1314 1315/******************************************************************************/ 1316void 1317__EraseMemory(void *mem, UInt32 size) 1318{ 1319 if (mem) { 1320 // overwrite with 1s, then 0s, just in case. Just in case why? Just do it, K? 1321 memset(mem, 0xFF, size); 1322 memset(mem, 0x00, size); 1323 } 1324} 1325 1326/******************************************************************************/ 1327void __EraseDataArray(OSArray *target) 1328{ 1329 OSCollectionIterator *iterator = NULL; 1330 require(target, finished); 1331 1332 iterator = OSCollectionIterator::withCollection(target); 1333 require(iterator, finished); 1334 do { 1335 OSObject * obj = iterator->getNextObject(); 1336 if (!obj) { 1337 if (iterator->isValid()) { 1338 goto finished; 1339 } 1340 else { 1341 iterator->reset(); 1342 } 1343 } 1344 else { 1345 OSData *dict = OSDynamicCast(OSData, obj); 1346 __EraseData(dict); 1347 } 1348 } 1349 while (true); 1350 1351finished: 1352 if (iterator) 1353 iterator->release(); 1354} 1355 1356/******************************************************************************/ 1357IOReturn 1358IOHIDSecurePromptClient::ensureBufferSize(UInt32 size) 1359{ 1360 IOReturn result = kIOReturnSuccess; 1361 UInt8 *oldBuffer = NULL; 1362 UInt32 oldBufferSize = 0; 1363 UInt8 *newBuffer = NULL; 1364 UInt8 *newKeystrokeOffset; 1365 UInt32 newBufferSize = 0; 1366 UInt32 newSize = size; 1367 1368 if (_reserved->bufferLength >= size) 1369 goto finished; 1370 if (!size) { 1371 oldBuffer = (UInt8*)_reserved->unicode; 1372 oldBufferSize = _reserved->bufferLength * (sizeof(UTF32Char) + sizeof(IOHIDSecurePromptClient_RawKeystrokeData)); 1373 goto finished; 1374 } 1375 1376 // round size up to next power of two 1377 newSize--; 1378 newSize |= newSize >> 1; 1379 newSize |= newSize >> 2; 1380 newSize |= newSize >> 4; 1381 newSize |= newSize >> 8; 1382 newSize |= newSize >> 16; 1383 newSize++; 1384 1385 result = kIOReturnNoMemory; 1386 require(newSize < 1024, finished); 1387 1388 newBufferSize = newSize * (sizeof(UTF32Char) + sizeof(IOHIDSecurePromptClient_RawKeystrokeData)); 1389 newBuffer = (UInt8*)IOMalloc(newBufferSize); 1390 require(newBuffer, finished); 1391 newKeystrokeOffset = newBuffer + newSize * sizeof(UTF32Char); 1392 memcpy(newBuffer, _reserved->unicode, _reserved->stringLength * sizeof(UTF32Char)); 1393 memcpy(newKeystrokeOffset, _reserved->rawKeystrokes, _reserved->stringLength * sizeof(IOHIDSecurePromptClient_RawKeystrokeData)); 1394 oldBuffer = (UInt8*)_reserved->unicode; 1395 oldBufferSize = _reserved->bufferLength * (sizeof(UTF32Char) + sizeof(IOHIDSecurePromptClient_RawKeystrokeData)); 1396 _reserved->unicode = (UTF32Char*)newBuffer; 1397 _reserved->rawKeystrokes = (IOHIDSecurePromptClient_RawKeystrokeData*)newKeystrokeOffset; 1398 _reserved->bufferLength = newSize; 1399 newBuffer = NULL; 1400 result = kIOReturnSuccess; 1401 1402finished: 1403 if (newBuffer) 1404 IOFree(newBuffer, newBufferSize); 1405 if (oldBuffer) { 1406 __EraseMemory(oldBuffer, oldBufferSize); 1407 IOFree(oldBuffer, oldBufferSize); 1408 } 1409 1410 return result; 1411} 1412 1413/******************************************************************************/ 1414void 1415__InsertBytes(void *dest, UInt32 insertPoint, UInt32 destCount, void *source, UInt32 sourceCount, UInt32 size) 1416{ 1417 UInt8 *destBytes = (UInt8*)dest; 1418 UInt8 *sourceBytes = (UInt8*)source; 1419 require(destBytes && sourceBytes && sourceCount && size, bad_parameter); 1420 if (insertPoint > destCount) { 1421 insertPoint = destCount; 1422 } 1423 if (insertPoint < destCount) { 1424 memmove(destBytes + (insertPoint + sourceCount) * size, destBytes + insertPoint * size, sourceCount * size); 1425 } 1426 memcpy(destBytes + insertPoint * size, sourceBytes, sourceCount * size); 1427 1428bad_parameter: 1429 ; 1430} 1431 1432/******************************************************************************/ 1433 1434/******************************************************************************/ 1435