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