1 /* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 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. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 #include <sys/cdefs.h> 30 #include <stdbool.h> 31 32 #include <IOKit/assert.h> 33 #include <IOKit/system.h> 34 #include <IOKit/IOLib.h> 35 #include <IOKit/IOMemoryDescriptor.h> 36 #include <IOKit/IOKitDebug.h> 37 38 __BEGIN_DECLS 39 40 #include <pexpert/pexpert.h> 41 42 static volatile UInt32 alreadyFetched = 0; 43 static IOMemoryDescriptor * newData; 44 45 IOMemoryDescriptor * 46 IOGetBootKeyStoreData(void); 47 void 48 IOSetKeyStoreData(IOMemoryDescriptor * data); 49 50 // APFS 51 static volatile UInt32 apfsKeyFetched = 0; 52 static IOMemoryDescriptor* apfsKeyData = NULL; 53 54 IOMemoryDescriptor* IOGetAPFSKeyStoreData(); 55 void IOSetAPFSKeyStoreData(IOMemoryDescriptor* data); 56 57 __END_DECLS 58 59 #if 1 60 #define DEBG(fmt, args...) { kprintf(fmt, ## args); } 61 #else 62 #define DEBG(fmt, args...) {} 63 #endif 64 65 void 66 IOSetKeyStoreData(IOMemoryDescriptor * data) 67 { 68 newData = data; 69 alreadyFetched = 0; 70 } 71 72 IOMemoryDescriptor * 73 IOGetBootKeyStoreData(void) 74 { 75 IOMemoryDescriptor *memoryDescriptor; 76 boot_args *args = (boot_args *)PE_state.bootArgs; 77 IOOptionBits options; 78 IOAddressRange ranges; 79 80 if (!OSCompareAndSwap(0, 1, &alreadyFetched)) 81 return (NULL); 82 83 if (newData) 84 { 85 IOMemoryDescriptor * data = newData; 86 newData = NULL; 87 return (data); 88 } 89 90 DEBG("%s: data at address %u size %u\n", __func__, 91 args->keyStoreDataStart, 92 args->keyStoreDataSize); 93 94 if (args->keyStoreDataStart == 0) 95 return (NULL); 96 97 ranges.address = args->keyStoreDataStart; 98 ranges.length = args->keyStoreDataSize; 99 100 options = kIODirectionInOut | kIOMemoryTypePhysical64 | kIOMemoryMapperNone; 101 102 memoryDescriptor = IOMemoryDescriptor::withOptions(&ranges, 103 1, 104 0, 105 NULL, 106 options); 107 108 DEBG("%s: memory descriptor %p\n", __func__, memoryDescriptor); 109 110 return memoryDescriptor; 111 } 112 113 // APFS volume key fetcher 114 115 // Store in-memory key (could be used by IOHibernateDone) 116 void 117 IOSetAPFSKeyStoreData(IOMemoryDescriptor* data) 118 { 119 // Do not allow re-fetching of the boot_args key by passing NULL here. 120 if (data != NULL) 121 { 122 apfsKeyData = data; 123 apfsKeyFetched = 0; 124 } 125 } 126 127 // Retrieve any key we may have (stored in boot_args or by Hibernate) 128 IOMemoryDescriptor* 129 IOGetAPFSKeyStoreData() 130 { 131 // Check if someone got the key before us 132 if (!OSCompareAndSwap(0, 1, &apfsKeyFetched)) 133 return NULL; 134 135 // Do we have in-memory key? 136 if (apfsKeyData) 137 { 138 IOMemoryDescriptor* data = apfsKeyData; 139 apfsKeyData = NULL; 140 return data; 141 } 142 143 // Looks like there was no in-memory key and it's the first call - try boot_args 144 boot_args* args = (boot_args*)PE_state.bootArgs; 145 146 DEBG("%s: data at address %u size %u\n", __func__, args->apfsDataStart, args->apfsDataSize); 147 if (args->apfsDataStart == 0) 148 return NULL; 149 150 // We have the key in the boot_args, create IOMemoryDescriptor for the blob 151 IOAddressRange ranges; 152 ranges.address = args->apfsDataStart; 153 ranges.length = args->apfsDataSize; 154 155 const IOOptionBits options = kIODirectionInOut | kIOMemoryTypePhysical64 | kIOMemoryMapperNone; 156 157 IOMemoryDescriptor* memoryDescriptor = IOMemoryDescriptor::withOptions(&ranges, 1, 0, NULL, options); 158 DEBG("%s: memory descriptor %p\n", __func__, memoryDescriptor); 159 return memoryDescriptor; 160 } 161