1 | /** @file
|
---|
2 | Provides generic security measurement functions for DXE module.
|
---|
3 |
|
---|
4 | Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
|
---|
5 | This program and the accompanying materials
|
---|
6 | are licensed and made available under the terms and conditions of the BSD License
|
---|
7 | which accompanies this distribution. The full text of the license may be found at
|
---|
8 | http://opensource.org/licenses/bsd-license.php
|
---|
9 |
|
---|
10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
---|
11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
---|
12 |
|
---|
13 | **/
|
---|
14 |
|
---|
15 | #include <PiDxe.h>
|
---|
16 | #include <Library/DebugLib.h>
|
---|
17 | #include <Library/DxeServicesLib.h>
|
---|
18 | #include <Library/MemoryAllocationLib.h>
|
---|
19 | #include <Library/SecurityManagementLib.h>
|
---|
20 |
|
---|
21 | #define SECURITY_HANDLER_TABLE_SIZE 0x10
|
---|
22 |
|
---|
23 | #define EFI_AUTH_OPERATION_MASK (EFI_AUTH_OPERATION_VERIFY_IMAGE \
|
---|
24 | | EFI_AUTH_OPERATION_DEFER_IMAGE_LOAD \
|
---|
25 | | EFI_AUTH_OPERATION_MEASURE_IMAGE)
|
---|
26 |
|
---|
27 | typedef struct {
|
---|
28 | UINT32 SecurityOperation;
|
---|
29 | SECURITY_FILE_AUTHENTICATION_STATE_HANDLER SecurityHandler;
|
---|
30 | } SECURITY_INFO;
|
---|
31 |
|
---|
32 | UINT32 mCurrentAuthOperation = 0;
|
---|
33 | UINT32 mNumberOfSecurityHandler = 0;
|
---|
34 | UINT32 mMaxNumberOfSecurityHandler = 0;
|
---|
35 | SECURITY_INFO *mSecurityTable = NULL;
|
---|
36 |
|
---|
37 | /**
|
---|
38 | Reallocates more global memory to store the registered Handler list.
|
---|
39 |
|
---|
40 | @retval RETURN_SUCCESS Reallocate memory successfully.
|
---|
41 | @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated.
|
---|
42 | **/
|
---|
43 | RETURN_STATUS
|
---|
44 | EFIAPI
|
---|
45 | ReallocateSecurityHandlerTable (
|
---|
46 | )
|
---|
47 | {
|
---|
48 | //
|
---|
49 | // Reallocate memory for security info structure.
|
---|
50 | //
|
---|
51 | mSecurityTable = ReallocatePool (
|
---|
52 | mMaxNumberOfSecurityHandler * sizeof (SECURITY_INFO),
|
---|
53 | (mMaxNumberOfSecurityHandler + SECURITY_HANDLER_TABLE_SIZE) * sizeof (SECURITY_INFO),
|
---|
54 | mSecurityTable
|
---|
55 | );
|
---|
56 |
|
---|
57 | //
|
---|
58 | // No enough resource is allocated.
|
---|
59 | //
|
---|
60 | if (mSecurityTable == NULL) {
|
---|
61 | return RETURN_OUT_OF_RESOURCES;
|
---|
62 | }
|
---|
63 |
|
---|
64 | //
|
---|
65 | // Increase max handler number
|
---|
66 | //
|
---|
67 | mMaxNumberOfSecurityHandler = mMaxNumberOfSecurityHandler + SECURITY_HANDLER_TABLE_SIZE;
|
---|
68 | return RETURN_SUCCESS;
|
---|
69 | }
|
---|
70 |
|
---|
71 | /**
|
---|
72 | Check whether an operation is valid according to the requirement of current operation,
|
---|
73 | which must make sure that the measure image operation is the last one.
|
---|
74 |
|
---|
75 | @param CurrentAuthOperation Current operation.
|
---|
76 | @param CheckAuthOperation Operation to be checked.
|
---|
77 |
|
---|
78 | @retval TRUE Operation is valid for current operation.
|
---|
79 | @retval FALSE Operation is invalid for current operation.
|
---|
80 | **/
|
---|
81 | BOOLEAN
|
---|
82 | CheckAuthenticationOperation (
|
---|
83 | IN UINT32 CurrentAuthOperation,
|
---|
84 | IN UINT32 CheckAuthOperation
|
---|
85 | )
|
---|
86 | {
|
---|
87 | //
|
---|
88 | // Make sure new auth operation can be recognized.
|
---|
89 | //
|
---|
90 | ASSERT ((CheckAuthOperation & ~(EFI_AUTH_OPERATION_MASK | EFI_AUTH_OPERATION_IMAGE_REQUIRED)) == 0);
|
---|
91 |
|
---|
92 | //
|
---|
93 | // When current operation includes measure image operation,
|
---|
94 | // only another measure image operation or none operation will be allowed.
|
---|
95 | //
|
---|
96 | if ((CurrentAuthOperation & EFI_AUTH_OPERATION_MEASURE_IMAGE) == EFI_AUTH_OPERATION_MEASURE_IMAGE) {
|
---|
97 | if (((CheckAuthOperation & EFI_AUTH_OPERATION_MEASURE_IMAGE) == EFI_AUTH_OPERATION_MEASURE_IMAGE) ||
|
---|
98 | ((CheckAuthOperation & EFI_AUTH_OPERATION_MASK) == EFI_AUTH_OPERATION_NONE)) {
|
---|
99 | return TRUE;
|
---|
100 | } else {
|
---|
101 | return FALSE;
|
---|
102 | }
|
---|
103 | }
|
---|
104 |
|
---|
105 | //
|
---|
106 | // When current operation doesn't include measure image operation,
|
---|
107 | // any new operation will be allowed.
|
---|
108 | //
|
---|
109 | return TRUE;
|
---|
110 | }
|
---|
111 |
|
---|
112 | /**
|
---|
113 | Register security measurement handler with its operation type. The different
|
---|
114 | handler with the same operation can all be registered.
|
---|
115 |
|
---|
116 | If SecurityHandler is NULL, then ASSERT().
|
---|
117 | If no enough resources available to register new handler, then ASSERT().
|
---|
118 | If AuthenticationOperation is not recongnized, then ASSERT().
|
---|
119 | If the previous register handler can't be executed before the later register handler, then ASSERT().
|
---|
120 |
|
---|
121 | @param[in] SecurityHandler Security measurement service handler to be registered.
|
---|
122 | @param[in] AuthenticationOperation Operation type is specified for the registered handler.
|
---|
123 |
|
---|
124 | @retval EFI_SUCCESS The handlers were registered successfully.
|
---|
125 | **/
|
---|
126 | EFI_STATUS
|
---|
127 | EFIAPI
|
---|
128 | RegisterSecurityHandler (
|
---|
129 | IN SECURITY_FILE_AUTHENTICATION_STATE_HANDLER SecurityHandler,
|
---|
130 | IN UINT32 AuthenticationOperation
|
---|
131 | )
|
---|
132 | {
|
---|
133 | EFI_STATUS Status;
|
---|
134 |
|
---|
135 | ASSERT (SecurityHandler != NULL);
|
---|
136 |
|
---|
137 | //
|
---|
138 | // Make sure AuthenticationOperation is valid in the register order.
|
---|
139 | //
|
---|
140 | ASSERT (CheckAuthenticationOperation (mCurrentAuthOperation, AuthenticationOperation));
|
---|
141 | mCurrentAuthOperation = mCurrentAuthOperation | AuthenticationOperation;
|
---|
142 |
|
---|
143 | //
|
---|
144 | // Check whether the handler lists is enough to store new handler.
|
---|
145 | //
|
---|
146 | if (mNumberOfSecurityHandler == mMaxNumberOfSecurityHandler) {
|
---|
147 | //
|
---|
148 | // Allocate more resources for new handler.
|
---|
149 | //
|
---|
150 | Status = ReallocateSecurityHandlerTable();
|
---|
151 | ASSERT_EFI_ERROR (Status);
|
---|
152 | }
|
---|
153 |
|
---|
154 | //
|
---|
155 | // Register new handler into the handler list.
|
---|
156 | //
|
---|
157 | mSecurityTable[mNumberOfSecurityHandler].SecurityOperation = AuthenticationOperation;
|
---|
158 | mSecurityTable[mNumberOfSecurityHandler].SecurityHandler = SecurityHandler;
|
---|
159 | mNumberOfSecurityHandler ++;
|
---|
160 |
|
---|
161 | return EFI_SUCCESS;
|
---|
162 | }
|
---|
163 |
|
---|
164 | /**
|
---|
165 | Execute registered handlers until one returns an error and that error is returned.
|
---|
166 | If none of the handlers return an error, then EFI_SUCCESS is returned.
|
---|
167 |
|
---|
168 | Before exectue handler, get the image buffer by file device path if a handler
|
---|
169 | requires the image file. And return the image buffer to each handler when exectue handler.
|
---|
170 |
|
---|
171 | The handlers are executed in same order to their registered order.
|
---|
172 |
|
---|
173 | @param[in] AuthenticationStatus
|
---|
174 | This is the authentication type returned from the Section
|
---|
175 | Extraction protocol. See the Section Extraction Protocol
|
---|
176 | Specification for details on this type.
|
---|
177 | @param[in] FilePath This is a pointer to the device path of the file that is
|
---|
178 | being dispatched. This will optionally be used for logging.
|
---|
179 |
|
---|
180 | @retval EFI_SUCCESS The file specified by File did authenticate when more
|
---|
181 | than one security handler services were registered,
|
---|
182 | or the file did not authenticate when no security
|
---|
183 | handler service was registered. And the platform policy
|
---|
184 | dictates that the DXE Core may use File.
|
---|
185 | @retval EFI_INVALID_PARAMETER File is NULL.
|
---|
186 | @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
|
---|
187 | the platform policy dictates that File should be placed
|
---|
188 | in the untrusted state. A file may be promoted from
|
---|
189 | the untrusted to the trusted state at a future time
|
---|
190 | with a call to the Trust() DXE Service.
|
---|
191 | @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
|
---|
192 | the platform policy dictates that File should not be
|
---|
193 | used for any purpose.
|
---|
194 | **/
|
---|
195 | EFI_STATUS
|
---|
196 | EFIAPI
|
---|
197 | ExecuteSecurityHandlers (
|
---|
198 | IN UINT32 AuthenticationStatus,
|
---|
199 | IN CONST EFI_DEVICE_PATH_PROTOCOL *FilePath
|
---|
200 | )
|
---|
201 | {
|
---|
202 | UINT32 Index;
|
---|
203 | EFI_STATUS Status;
|
---|
204 | UINT32 HandlerAuthenticationStatus;
|
---|
205 | VOID *FileBuffer;
|
---|
206 | UINTN FileSize;
|
---|
207 |
|
---|
208 | if (FilePath == NULL) {
|
---|
209 | return EFI_INVALID_PARAMETER;
|
---|
210 | }
|
---|
211 |
|
---|
212 | //
|
---|
213 | // Directly return successfully when no handler is registered.
|
---|
214 | //
|
---|
215 | if (mNumberOfSecurityHandler == 0) {
|
---|
216 | return EFI_SUCCESS;
|
---|
217 | }
|
---|
218 |
|
---|
219 | Status = EFI_SUCCESS;
|
---|
220 | FileBuffer = NULL;
|
---|
221 | FileSize = 0;
|
---|
222 | HandlerAuthenticationStatus = AuthenticationStatus;
|
---|
223 | //
|
---|
224 | // Run security handler in same order to their registered list
|
---|
225 | //
|
---|
226 | for (Index = 0; Index < mNumberOfSecurityHandler; Index ++) {
|
---|
227 | if ((mSecurityTable[Index].SecurityOperation & EFI_AUTH_OPERATION_IMAGE_REQUIRED) == EFI_AUTH_OPERATION_IMAGE_REQUIRED) {
|
---|
228 | //
|
---|
229 | // Try get file buffer when the handler requires image buffer.
|
---|
230 | //
|
---|
231 | if (FileBuffer == NULL) {
|
---|
232 | //
|
---|
233 | // Try to get image by FALSE boot policy for the exact boot file path.
|
---|
234 | //
|
---|
235 | FileBuffer = GetFileBufferByFilePath (FALSE, FilePath, &FileSize, &AuthenticationStatus);
|
---|
236 | if (FileBuffer == NULL) {
|
---|
237 | //
|
---|
238 | // Try to get image by TRUE boot policy for the inexact boot file path.
|
---|
239 | //
|
---|
240 | FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, &FileSize, &AuthenticationStatus);
|
---|
241 | }
|
---|
242 | }
|
---|
243 | }
|
---|
244 | Status = mSecurityTable[Index].SecurityHandler (
|
---|
245 | HandlerAuthenticationStatus,
|
---|
246 | FilePath,
|
---|
247 | FileBuffer,
|
---|
248 | FileSize
|
---|
249 | );
|
---|
250 | if (EFI_ERROR (Status)) {
|
---|
251 | break;
|
---|
252 | }
|
---|
253 | }
|
---|
254 |
|
---|
255 | if (FileBuffer != NULL) {
|
---|
256 | FreePool (FileBuffer);
|
---|
257 | }
|
---|
258 |
|
---|
259 | return Status;
|
---|
260 | }
|
---|