]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.c
Update the copyright notice format
[mirror_edk2.git] / MdeModulePkg / Library / DxeSecurityManagementLib / DxeSecurityManagementLib.c
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 }