1 /** @file
2   Helper functions for SecureBoot configuration module.
3 
4 Copyright (c) 2015, 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 "SecureBootConfigImpl.h"
16 
17 /**
18   Read file content into BufferPtr, the size of the allocate buffer
19   is *FileSize plus AddtionAllocateSize.
20 
21   @param[in]       FileHandle            The file to be read.
22   @param[in, out]  BufferPtr             Pointers to the pointer of allocated buffer.
23   @param[out]      FileSize              Size of input file
24   @param[in]       AddtionAllocateSize   Addtion size the buffer need to be allocated.
25                                          In case the buffer need to contain others besides the file content.
26 
27   @retval   EFI_SUCCESS                  The file was read into the buffer.
28   @retval   EFI_INVALID_PARAMETER        A parameter was invalid.
29   @retval   EFI_OUT_OF_RESOURCES         A memory allocation failed.
30   @retval   others                       Unexpected error.
31 
32 **/
33 EFI_STATUS
ReadFileContent(IN EFI_FILE_HANDLE FileHandle,IN OUT VOID ** BufferPtr,OUT UINTN * FileSize,IN UINTN AddtionAllocateSize)34 ReadFileContent (
35   IN      EFI_FILE_HANDLE           FileHandle,
36   IN OUT  VOID                      **BufferPtr,
37      OUT  UINTN                     *FileSize,
38   IN      UINTN                     AddtionAllocateSize
39   )
40 
41 {
42   UINTN      BufferSize;
43   UINT64     SourceFileSize;
44   VOID       *Buffer;
45   EFI_STATUS Status;
46 
47   if ((FileHandle == NULL) || (FileSize == NULL)) {
48     return EFI_INVALID_PARAMETER;
49   }
50 
51   Buffer = NULL;
52 
53   //
54   // Get the file size
55   //
56   Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);
57   if (EFI_ERROR (Status)) {
58     goto ON_EXIT;
59   }
60 
61   Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);
62   if (EFI_ERROR (Status)) {
63     goto ON_EXIT;
64   }
65 
66   Status = FileHandle->SetPosition (FileHandle, 0);
67   if (EFI_ERROR (Status)) {
68     goto ON_EXIT;
69   }
70 
71   BufferSize = (UINTN) SourceFileSize + AddtionAllocateSize;
72   Buffer =  AllocateZeroPool(BufferSize);
73   if (Buffer == NULL) {
74     return EFI_OUT_OF_RESOURCES;
75   }
76 
77   BufferSize = (UINTN) SourceFileSize;
78   *FileSize  = BufferSize;
79 
80   Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);
81   if (EFI_ERROR (Status) || BufferSize != *FileSize) {
82     FreePool (Buffer);
83     Buffer = NULL;
84     Status  = EFI_BAD_BUFFER_SIZE;
85     goto ON_EXIT;
86   }
87 
88 ON_EXIT:
89 
90   *BufferPtr = Buffer;
91   return Status;
92 }
93 
94 /**
95   Close an open file handle.
96 
97   @param[in] FileHandle           The file handle to close.
98 
99 **/
100 VOID
CloseFile(IN EFI_FILE_HANDLE FileHandle)101 CloseFile (
102   IN EFI_FILE_HANDLE   FileHandle
103   )
104 {
105   if (FileHandle != NULL) {
106     FileHandle->Close (FileHandle);
107   }
108 }
109 
110 /**
111   Convert a nonnegative integer to an octet string of a specified length.
112 
113   @param[in]   Integer          Pointer to the nonnegative integer to be converted
114   @param[in]   IntSizeInWords   Length of integer buffer in words
115   @param[out]  OctetString      Converted octet string of the specified length
116   @param[in]   OSSizeInBytes    Intended length of resulting octet string in bytes
117 
118 Returns:
119 
120   @retval   EFI_SUCCESS            Data conversion successfully
121   @retval   EFI_BUFFER_TOOL_SMALL  Buffer is too small for output string
122 
123 **/
124 EFI_STATUS
125 EFIAPI
Int2OctStr(IN CONST UINTN * Integer,IN UINTN IntSizeInWords,OUT UINT8 * OctetString,IN UINTN OSSizeInBytes)126 Int2OctStr (
127   IN     CONST UINTN                *Integer,
128   IN     UINTN                      IntSizeInWords,
129      OUT UINT8                      *OctetString,
130   IN     UINTN                      OSSizeInBytes
131   )
132 {
133   CONST UINT8  *Ptr1;
134   UINT8        *Ptr2;
135 
136   for (Ptr1 = (CONST UINT8 *)Integer, Ptr2 = OctetString + OSSizeInBytes - 1;
137        Ptr1 < (UINT8 *)(Integer + IntSizeInWords) && Ptr2 >= OctetString;
138        Ptr1++, Ptr2--) {
139     *Ptr2 = *Ptr1;
140   }
141 
142   for (; Ptr1 < (CONST UINT8 *)(Integer + IntSizeInWords) && *Ptr1 == 0; Ptr1++);
143 
144   if (Ptr1 < (CONST UINT8 *)(Integer + IntSizeInWords)) {
145     return EFI_BUFFER_TOO_SMALL;
146   }
147 
148   if (Ptr2 >= OctetString) {
149     ZeroMem (OctetString, Ptr2 - OctetString + 1);
150   }
151 
152   return EFI_SUCCESS;
153 }
154 
155 
156 
157 /**
158   Convert a String to Guid Value.
159 
160   @param[in]   Str        Specifies the String to be converted.
161   @param[in]   StrLen     Number of Unicode Characters of String (exclusive \0)
162   @param[out]  Guid       Return the result Guid value.
163 
164   @retval    EFI_SUCCESS           The operation is finished successfully.
165   @retval    EFI_NOT_FOUND         Invalid string.
166 
167 **/
168 EFI_STATUS
StringToGuid(IN CHAR16 * Str,IN UINTN StrLen,OUT EFI_GUID * Guid)169 StringToGuid (
170   IN   CHAR16           *Str,
171   IN   UINTN            StrLen,
172   OUT  EFI_GUID         *Guid
173   )
174 {
175   CHAR16             *PtrBuffer;
176   CHAR16             *PtrPosition;
177   UINT16             *Buffer;
178   UINTN              Data;
179   UINTN              Index;
180   UINT16             Digits[3];
181 
182   Buffer = (CHAR16 *) AllocateZeroPool (sizeof (CHAR16) * (StrLen + 1));
183   if (Buffer == NULL) {
184     return EFI_OUT_OF_RESOURCES;
185   }
186 
187   StrCpyS (Buffer, (StrLen + 1), Str);
188 
189   //
190   // Data1
191   //
192   PtrBuffer       = Buffer;
193   PtrPosition     = PtrBuffer;
194   while (*PtrBuffer != L'\0') {
195     if (*PtrBuffer == L'-') {
196       break;
197     }
198     PtrBuffer++;
199   }
200   if (*PtrBuffer == L'\0') {
201     FreePool (Buffer);
202     return EFI_NOT_FOUND;
203   }
204 
205   *PtrBuffer      = L'\0';
206   Data            = StrHexToUintn (PtrPosition);
207   Guid->Data1     = (UINT32)Data;
208 
209   //
210   // Data2
211   //
212   PtrBuffer++;
213   PtrPosition     = PtrBuffer;
214   while (*PtrBuffer != L'\0') {
215     if (*PtrBuffer == L'-') {
216       break;
217     }
218     PtrBuffer++;
219   }
220   if (*PtrBuffer == L'\0') {
221     FreePool (Buffer);
222     return EFI_NOT_FOUND;
223   }
224   *PtrBuffer      = L'\0';
225   Data            = StrHexToUintn (PtrPosition);
226   Guid->Data2     = (UINT16)Data;
227 
228   //
229   // Data3
230   //
231   PtrBuffer++;
232   PtrPosition     = PtrBuffer;
233   while (*PtrBuffer != L'\0') {
234     if (*PtrBuffer == L'-') {
235       break;
236     }
237     PtrBuffer++;
238   }
239   if (*PtrBuffer == L'\0') {
240     FreePool (Buffer);
241     return EFI_NOT_FOUND;
242   }
243   *PtrBuffer      = L'\0';
244   Data            = StrHexToUintn (PtrPosition);
245   Guid->Data3     = (UINT16)Data;
246 
247   //
248   // Data4[0..1]
249   //
250   for ( Index = 0 ; Index < 2 ; Index++) {
251     PtrBuffer++;
252     if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) {
253       FreePool (Buffer);
254       return EFI_NOT_FOUND;
255     }
256     Digits[0]     = *PtrBuffer;
257     PtrBuffer++;
258     Digits[1]     = *PtrBuffer;
259     Digits[2]     = L'\0';
260     Data          = StrHexToUintn (Digits);
261     Guid->Data4[Index] = (UINT8)Data;
262   }
263 
264   //
265   // skip the '-'
266   //
267   PtrBuffer++;
268   if ((*PtrBuffer != L'-' ) || ( *PtrBuffer == L'\0')) {
269     return EFI_NOT_FOUND;
270   }
271 
272   //
273   // Data4[2..7]
274   //
275   for ( ; Index < 8; Index++) {
276     PtrBuffer++;
277     if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) {
278       FreePool (Buffer);
279       return EFI_NOT_FOUND;
280     }
281     Digits[0]     = *PtrBuffer;
282     PtrBuffer++;
283     Digits[1]     = *PtrBuffer;
284     Digits[2]     = L'\0';
285     Data          = StrHexToUintn (Digits);
286     Guid->Data4[Index] = (UINT8)Data;
287   }
288 
289   FreePool (Buffer);
290 
291   return EFI_SUCCESS;
292 }
293 
294 /**
295   Worker function that prints an EFI_GUID into specified Buffer.
296 
297   @param[in]     Guid          Pointer to GUID to print.
298   @param[in]     Buffer        Buffer to print Guid into.
299   @param[in]     BufferSize    Size of Buffer.
300 
301   @retval    Number of characters printed.
302 
303 **/
304 UINTN
GuidToString(IN EFI_GUID * Guid,IN CHAR16 * Buffer,IN UINTN BufferSize)305 GuidToString (
306   IN  EFI_GUID  *Guid,
307   IN  CHAR16    *Buffer,
308   IN  UINTN     BufferSize
309   )
310 {
311   UINTN Size;
312 
313   Size = UnicodeSPrint (
314             Buffer,
315             BufferSize,
316             L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
317             (UINTN)Guid->Data1,
318             (UINTN)Guid->Data2,
319             (UINTN)Guid->Data3,
320             (UINTN)Guid->Data4[0],
321             (UINTN)Guid->Data4[1],
322             (UINTN)Guid->Data4[2],
323             (UINTN)Guid->Data4[3],
324             (UINTN)Guid->Data4[4],
325             (UINTN)Guid->Data4[5],
326             (UINTN)Guid->Data4[6],
327             (UINTN)Guid->Data4[7]
328             );
329 
330   //
331   // SPrint will null terminate the string. The -1 skips the null
332   //
333   return Size - 1;
334 }
335