]>
Commit | Line | Data |
---|---|---|
8b63877a KM |
1 | ## @file\r |
2 | # Generate a capsule.\r | |
3 | #\r | |
4 | # Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r | |
5 | # This program and the accompanying materials\r | |
6 | # are licensed and made available under the terms and conditions of the BSD License\r | |
7 | # which accompanies this distribution. The full text of the license may be found at\r | |
8 | # http://opensource.org/licenses/bsd-license.php\r | |
9 | #\r | |
10 | # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
11 | # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
12 | #\r | |
13 | \r | |
14 | '''\r | |
15 | GenerateCapsule\r | |
16 | '''\r | |
17 | \r | |
18 | import sys\r | |
19 | import argparse\r | |
20 | import uuid\r | |
21 | import struct\r | |
22 | import subprocess\r | |
23 | import os\r | |
24 | import tempfile\r | |
25 | import shutil\r | |
26 | import platform\r | |
27 | from Common.Uefi.Capsule.UefiCapsuleHeader import UefiCapsuleHeaderClass\r | |
28 | from Common.Uefi.Capsule.FmpCapsuleHeader import FmpCapsuleHeaderClass\r | |
29 | from Common.Uefi.Capsule.FmpAuthHeader import FmpAuthHeaderClass\r | |
30 | from Common.Edk2.Capsule.FmpPayloadHeader import FmpPayloadHeaderClass\r | |
31 | \r | |
32 | #\r | |
33 | # Globals for help information\r | |
34 | #\r | |
35 | __prog__ = 'GenerateCapsule'\r | |
36 | __version__ = '0.9'\r | |
37 | __copyright__ = 'Copyright (c) 2018, Intel Corporation. All rights reserved.'\r | |
38 | __description__ = 'Generate a capsule.\n'\r | |
39 | \r | |
40 | def SignPayloadSignTool (Payload, ToolPath, PfxFile):\r | |
41 | #\r | |
42 | # Create a temporary directory\r | |
43 | #\r | |
44 | TempDirectoryName = tempfile.mkdtemp()\r | |
45 | \r | |
46 | #\r | |
47 | # Generate temp file name for the payload contents\r | |
48 | #\r | |
49 | TempFileName = os.path.join (TempDirectoryName, 'Payload.bin')\r | |
50 | \r | |
51 | #\r | |
52 | # Create temporary payload file for signing\r | |
53 | #\r | |
54 | try:\r | |
55 | File = open (TempFileName, mode='wb')\r | |
56 | File.write (Payload)\r | |
57 | File.close ()\r | |
58 | except:\r | |
59 | shutil.rmtree (TempDirectoryName)\r | |
60 | raise ValueError ('GenerateCapsule: error: can not write temporary payload file.')\r | |
61 | \r | |
62 | #\r | |
63 | # Build signtool command\r | |
64 | #\r | |
65 | if ToolPath is None:\r | |
66 | ToolPath = ''\r | |
67 | Command = ''\r | |
68 | Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'signtool.exe'))\r | |
69 | Command = Command + 'sign /fd sha256 /p7ce DetachedSignedData /p7co 1.2.840.113549.1.7.2 '\r | |
70 | Command = Command + '/p7 {TempDir} '.format (TempDir = TempDirectoryName)\r | |
71 | Command = Command + '/f {PfxFile} '.format (PfxFile = PfxFile)\r | |
72 | Command = Command + TempFileName\r | |
73 | \r | |
74 | #\r | |
75 | # Sign the input file using the specified private key\r | |
76 | #\r | |
77 | try:\r | |
78 | Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)\r | |
79 | Result = Process.communicate('')\r | |
80 | except:\r | |
81 | shutil.rmtree (TempDirectoryName)\r | |
82 | raise ValueError ('GenerateCapsule: error: can not run signtool.')\r | |
83 | \r | |
84 | if Process.returncode != 0:\r | |
85 | shutil.rmtree (TempDirectoryName)\r | |
86 | print (Result[1].decode())\r | |
87 | raise ValueError ('GenerateCapsule: error: signtool failed.')\r | |
88 | \r | |
89 | #\r | |
90 | # Read the signature from the generated output file\r | |
91 | #\r | |
92 | try:\r | |
93 | File = open (TempFileName + '.p7', mode='rb')\r | |
94 | Signature = File.read ()\r | |
95 | File.close ()\r | |
96 | except:\r | |
97 | shutil.rmtree (TempDirectoryName)\r | |
98 | raise ValueError ('GenerateCapsule: error: can not read signature file.')\r | |
99 | \r | |
100 | shutil.rmtree (TempDirectoryName)\r | |
101 | return Signature\r | |
102 | \r | |
103 | def VerifyPayloadSignTool (Payload, CertData, ToolPath, PfxFile):\r | |
104 | print ('signtool verify is not supported.')\r | |
105 | raise ValueError ('GenerateCapsule: error: signtool verify is not supported.')\r | |
106 | \r | |
107 | def SignPayloadOpenSsl (Payload, ToolPath, SignerPrivateCertFile, OtherPublicCertFile, TrustedPublicCertFile):\r | |
108 | #\r | |
109 | # Build openssl command\r | |
110 | #\r | |
111 | if ToolPath is None:\r | |
112 | ToolPath = ''\r | |
113 | Command = ''\r | |
114 | Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'openssl'))\r | |
115 | Command = Command + 'smime -sign -binary -outform DER -md sha256 '\r | |
116 | Command = Command + '-signer "{Private}" -certfile "{Public}"'.format (Private = SignerPrivateCertFile, Public = OtherPublicCertFile)\r | |
117 | \r | |
118 | #\r | |
119 | # Sign the input file using the specified private key and capture signature from STDOUT\r | |
120 | #\r | |
121 | try:\r | |
122 | Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)\r | |
123 | Result = Process.communicate(input = Payload)\r | |
124 | Signature = Result[0]\r | |
125 | except:\r | |
126 | raise ValueError ('GenerateCapsule: error: can not run openssl.')\r | |
127 | \r | |
128 | if Process.returncode != 0:\r | |
129 | print (Result[1].decode())\r | |
130 | raise ValueError ('GenerateCapsule: error: openssl failed.')\r | |
131 | \r | |
132 | return Signature\r | |
133 | \r | |
134 | def VerifyPayloadOpenSsl (Payload, CertData, ToolPath, SignerPrivateCertFile, OtherPublicCertFile, TrustedPublicCertFile):\r | |
135 | #\r | |
136 | # Create a temporary directory\r | |
137 | #\r | |
138 | TempDirectoryName = tempfile.mkdtemp()\r | |
139 | \r | |
140 | #\r | |
141 | # Generate temp file name for the payload contents\r | |
142 | #\r | |
143 | TempFileName = os.path.join (TempDirectoryName, 'Payload.bin')\r | |
144 | \r | |
145 | #\r | |
146 | # Create temporary payload file for verification\r | |
147 | #\r | |
148 | try:\r | |
149 | File = open (TempFileName, mode='wb')\r | |
150 | File.write (Payload)\r | |
151 | File.close ()\r | |
152 | except:\r | |
153 | shutil.rmtree (TempDirectoryName)\r | |
154 | raise ValueError ('GenerateCapsule: error: can not write temporary payload file.')\r | |
155 | \r | |
156 | #\r | |
157 | # Build openssl command\r | |
158 | #\r | |
159 | if ToolPath is None:\r | |
160 | ToolPath = ''\r | |
161 | Command = ''\r | |
162 | Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'openssl'))\r | |
163 | Command = Command + 'smime -verify -inform DER '\r | |
164 | Command = Command + '-content {Content} -CAfile "{Public}"'.format (Content = TempFileName, Public = TrustedPublicCertFile)\r | |
165 | \r | |
166 | #\r | |
167 | # Verify signature\r | |
168 | #\r | |
169 | try:\r | |
170 | Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)\r | |
171 | Result = Process.communicate(input = CertData)\r | |
172 | except:\r | |
173 | shutil.rmtree (TempDirectoryName)\r | |
174 | raise ValueError ('GenerateCapsule: error: can not run openssl.')\r | |
175 | \r | |
176 | if Process.returncode != 0:\r | |
177 | shutil.rmtree (TempDirectoryName)\r | |
178 | print (Result[1].decode())\r | |
179 | raise ValueError ('GenerateCapsule: error: openssl failed.')\r | |
180 | \r | |
181 | shutil.rmtree (TempDirectoryName)\r | |
182 | return Payload\r | |
183 | \r | |
184 | if __name__ == '__main__':\r | |
185 | def convert_arg_line_to_args(arg_line):\r | |
186 | for arg in arg_line.split():\r | |
187 | if not arg.strip():\r | |
188 | continue\r | |
189 | yield arg\r | |
190 | \r | |
191 | def ValidateUnsignedInteger (Argument):\r | |
192 | try:\r | |
193 | Value = int (Argument, 0)\r | |
194 | except:\r | |
195 | Message = '{Argument} is not a valid integer value.'.format (Argument = Argument)\r | |
196 | raise argparse.ArgumentTypeError (Message)\r | |
197 | if Value < 0:\r | |
198 | Message = '{Argument} is a negative value.'.format (Argument = Argument)\r | |
199 | raise argparse.ArgumentTypeError (Message)\r | |
200 | return Value\r | |
201 | \r | |
202 | def ValidateRegistryFormatGuid (Argument):\r | |
203 | try:\r | |
204 | Value = uuid.UUID (Argument)\r | |
205 | except:\r | |
206 | Message = '{Argument} is not a valid registry format GUID value.'.format (Argument = Argument)\r | |
207 | raise argparse.ArgumentTypeError (Message)\r | |
208 | return Value\r | |
209 | \r | |
210 | #\r | |
211 | # Create command line argument parser object\r | |
212 | #\r | |
213 | parser = argparse.ArgumentParser (\r | |
214 | prog = __prog__,\r | |
215 | description = __description__ + __copyright__,\r | |
216 | conflict_handler = 'resolve',\r | |
217 | fromfile_prefix_chars = '@'\r | |
218 | )\r | |
219 | parser.convert_arg_line_to_args = convert_arg_line_to_args\r | |
220 | \r | |
221 | #\r | |
222 | # Add input and output file arguments\r | |
223 | #\r | |
224 | parser.add_argument("InputFile", type = argparse.FileType('rb'),\r | |
225 | help = "Input binary payload filename.")\r | |
226 | parser.add_argument("-o", "--output", dest = 'OutputFile', type = argparse.FileType('wb'),\r | |
227 | help = "Output filename.")\r | |
228 | #\r | |
229 | # Add group for -e and -d flags that are mutually exclusive and required\r | |
230 | #\r | |
231 | group = parser.add_mutually_exclusive_group (required = True)\r | |
232 | group.add_argument ("-e", "--encode", dest = 'Encode', action = "store_true",\r | |
233 | help = "Encode file")\r | |
234 | group.add_argument ("-d", "--decode", dest = 'Decode', action = "store_true",\r | |
235 | help = "Decode file")\r | |
236 | group.add_argument ("--dump-info", dest = 'DumpInfo', action = "store_true",\r | |
237 | help = "Display FMP Payload Header information")\r | |
238 | #\r | |
239 | # Add optional arguments for this command\r | |
240 | #\r | |
241 | parser.add_argument ("--capflag", dest = 'CapsuleFlag', action='append', default = [],\r | |
2779c222 KM |
242 | choices=['PersistAcrossReset', 'InitiateReset'],\r |
243 | help = "Capsule flag can be PersistAcrossReset or InitiateReset or not set")\r | |
8b63877a KM |
244 | parser.add_argument ("--capoemflag", dest = 'CapsuleOemFlag', type = ValidateUnsignedInteger, default = 0x0000,\r |
245 | help = "Capsule OEM Flag is an integer between 0x0000 and 0xffff.")\r | |
246 | \r | |
247 | parser.add_argument ("--guid", dest = 'Guid', type = ValidateRegistryFormatGuid,\r | |
248 | help = "The FMP/ESRT GUID in registry format. Required for encode operations.")\r | |
249 | parser.add_argument ("--hardware-instance", dest = 'HardwareInstance', type = ValidateUnsignedInteger, default = 0x0000000000000000,\r | |
250 | help = "The 64-bit hardware instance. The default is 0x0000000000000000")\r | |
251 | \r | |
252 | \r | |
253 | parser.add_argument ("--monotonic-count", dest = 'MonotonicCount', type = ValidateUnsignedInteger, default = 0x0000000000000000,\r | |
254 | help = "64-bit monotonic count value in header. Default is 0x0000000000000000.")\r | |
255 | \r | |
256 | parser.add_argument ("--fw-version", dest = 'FwVersion', type = ValidateUnsignedInteger,\r | |
257 | help = "The 32-bit version of the binary payload (e.g. 0x11223344 or 5678).")\r | |
258 | parser.add_argument ("--lsv", dest = 'LowestSupportedVersion', type = ValidateUnsignedInteger,\r | |
259 | help = "The 32-bit lowest supported version of the binary payload (e.g. 0x11223344 or 5678).")\r | |
260 | \r | |
261 | parser.add_argument ("--pfx-file", dest='SignToolPfxFile', type=argparse.FileType('rb'),\r | |
262 | help="signtool PFX certificate filename.")\r | |
263 | \r | |
264 | parser.add_argument ("--signer-private-cert", dest='OpenSslSignerPrivateCertFile', type=argparse.FileType('rb'),\r | |
265 | help="OpenSSL signer private certificate filename.")\r | |
266 | parser.add_argument ("--other-public-cert", dest='OpenSslOtherPublicCertFile', type=argparse.FileType('rb'),\r | |
267 | help="OpenSSL other public certificate filename.")\r | |
268 | parser.add_argument ("--trusted-public-cert", dest='OpenSslTrustedPublicCertFile', type=argparse.FileType('rb'),\r | |
269 | help="OpenSSL trusted public certificate filename.")\r | |
270 | \r | |
271 | parser.add_argument ("--signing-tool-path", dest = 'SigningToolPath',\r | |
272 | help = "Path to signtool or OpenSSL tool. Optional if path to tools are already in PATH.")\r | |
273 | \r | |
274 | #\r | |
275 | # Add optional arguments common to all operations\r | |
276 | #\r | |
277 | parser.add_argument ('--version', action='version', version='%(prog)s ' + __version__)\r | |
278 | parser.add_argument ("-v", "--verbose", dest = 'Verbose', action = "store_true",\r | |
279 | help = "Turn on verbose output with informational messages printed, including capsule headers and warning messages.")\r | |
280 | parser.add_argument ("-q", "--quiet", dest = 'Quiet', action = "store_true",\r | |
281 | help = "Disable all messages except fatal errors.")\r | |
282 | parser.add_argument ("--debug", dest = 'Debug', type = int, metavar = '[0-9]', choices = range (0, 10), default = 0,\r | |
283 | help = "Set debug level")\r | |
284 | \r | |
285 | #\r | |
286 | # Parse command line arguments\r | |
287 | #\r | |
288 | args = parser.parse_args()\r | |
289 | \r | |
290 | #\r | |
291 | # Perform additional argument verification\r | |
292 | #\r | |
293 | if args.Encode:\r | |
294 | if args.Guid is None:\r | |
295 | parser.error ('the following option is required: --guid')\r | |
296 | if 'PersistAcrossReset' not in args.CapsuleFlag:\r | |
8b63877a KM |
297 | if 'InitiateReset' in args.CapsuleFlag:\r |
298 | parser.error ('--capflag InitiateReset also requires --capflag PersistAcrossReset')\r | |
6ed4651c KM |
299 | if args.CapsuleOemFlag > 0xFFFF:\r |
300 | parser.error ('--capoemflag must be an integer between 0x0000 and 0xffff')\r | |
301 | if args.HardwareInstance > 0xFFFFFFFFFFFFFFFF:\r | |
302 | parser.error ('--hardware-instance must be an integer in range 0x0..0xffffffffffffffff')\r | |
303 | if args.MonotonicCount > 0xFFFFFFFFFFFFFFFF:\r | |
304 | parser.error ('--monotonic-count must be an integer in range 0x0..0xffffffffffffffff')\r | |
8b63877a KM |
305 | \r |
306 | UseSignTool = args.SignToolPfxFile is not None\r | |
307 | UseOpenSsl = (args.OpenSslSignerPrivateCertFile is not None and\r | |
308 | args.OpenSslOtherPublicCertFile is not None and\r | |
309 | args.OpenSslTrustedPublicCertFile is not None)\r | |
310 | AnyOpenSsl = (args.OpenSslSignerPrivateCertFile is not None or\r | |
311 | args.OpenSslOtherPublicCertFile is not None or\r | |
312 | args.OpenSslTrustedPublicCertFile is not None)\r | |
313 | if args.Encode or args.Decode:\r | |
314 | if args.OutputFile is None:\r | |
315 | parser.error ('the following option is required for all encode and decode operations: --output')\r | |
316 | \r | |
317 | if UseSignTool and AnyOpenSsl:\r | |
318 | parser.error ('Providing both signtool and OpenSSL options is not supported')\r | |
319 | if not UseSignTool and not UseOpenSsl and AnyOpenSsl:\r | |
320 | parser.error ('all the following options are required for OpenSSL: --signer-private-cert, --other-public-cert, --trusted-public-cert')\r | |
321 | if UseSignTool and platform.system() != 'Windows':\r | |
322 | parser.error ('Use of signtool is not supported on this operating system.')\r | |
323 | if args.Encode and (UseSignTool or UseOpenSsl):\r | |
324 | if args.FwVersion is None or args.LowestSupportedVersion is None:\r | |
325 | parser.error ('the following options are required: --fw-version, --lsv')\r | |
6ed4651c KM |
326 | if args.FwVersion > 0xFFFFFFFF:\r |
327 | parser.error ('--fw-version must be an integer in range 0x0..0xffffffff')\r | |
328 | if args.LowestSupportedVersion > 0xFFFFFFFF:\r | |
329 | parser.error ('--lsv must be an integer in range 0x0..0xffffffff')\r | |
8b63877a KM |
330 | \r |
331 | if UseSignTool:\r | |
332 | args.SignToolPfxFile.close()\r | |
333 | args.SignToolPfxFile = args.SignToolPfxFile.name\r | |
334 | if UseOpenSsl:\r | |
335 | args.OpenSslSignerPrivateCertFile.close()\r | |
336 | args.OpenSslOtherPublicCertFile.close()\r | |
337 | args.OpenSslTrustedPublicCertFile.close()\r | |
338 | args.OpenSslSignerPrivateCertFile = args.OpenSslSignerPrivateCertFile.name\r | |
339 | args.OpenSslOtherPublicCertFile = args.OpenSslOtherPublicCertFile.name\r | |
340 | args.OpenSslTrustedPublicCertFile = args.OpenSslTrustedPublicCertFile.name\r | |
341 | \r | |
f33d5d68 KM |
342 | if args.DumpInfo:\r |
343 | if args.OutputFile is not None:\r | |
344 | parser.error ('the following option is not supported for dumpinfo operations: --output')\r | |
345 | \r | |
8b63877a KM |
346 | #\r |
347 | # Read binary input file\r | |
348 | #\r | |
349 | try:\r | |
350 | if args.Verbose:\r | |
351 | print ('Read binary input file {File}'.format (File = args.InputFile.name))\r | |
352 | Buffer = args.InputFile.read ()\r | |
353 | args.InputFile.close ()\r | |
354 | except:\r | |
355 | print ('GenerateCapsule: error: can not read binary input file {File}'.format (File = args.InputFile.name))\r | |
356 | sys.exit (1)\r | |
357 | \r | |
358 | #\r | |
359 | # Create objects\r | |
360 | #\r | |
361 | UefiCapsuleHeader = UefiCapsuleHeaderClass ()\r | |
362 | FmpCapsuleHeader = FmpCapsuleHeaderClass ()\r | |
363 | FmpAuthHeader = FmpAuthHeaderClass ()\r | |
364 | FmpPayloadHeader = FmpPayloadHeaderClass ()\r | |
365 | \r | |
366 | if args.Encode:\r | |
367 | Result = Buffer\r | |
368 | if UseSignTool or UseOpenSsl:\r | |
369 | try:\r | |
370 | FmpPayloadHeader.FwVersion = args.FwVersion\r | |
371 | FmpPayloadHeader.LowestSupportedVersion = args.LowestSupportedVersion\r | |
372 | FmpPayloadHeader.Payload = Result\r | |
373 | Result = FmpPayloadHeader.Encode ()\r | |
374 | if args.Verbose:\r | |
375 | FmpPayloadHeader.DumpInfo ()\r | |
376 | except:\r | |
377 | print ('GenerateCapsule: error: can not encode FMP Payload Header')\r | |
378 | sys.exit (1)\r | |
379 | \r | |
380 | #\r | |
381 | # Sign image with 64-bit MonotonicCount appended to end of image\r | |
382 | #\r | |
383 | try:\r | |
384 | if UseSignTool:\r | |
385 | CertData = SignPayloadSignTool (\r | |
386 | Result + struct.pack ('<Q', args.MonotonicCount),\r | |
387 | args.SigningToolPath,\r | |
388 | args.SignToolPfxFile\r | |
389 | )\r | |
390 | else:\r | |
391 | CertData = SignPayloadOpenSsl (\r | |
392 | Result + struct.pack ('<Q', args.MonotonicCount),\r | |
393 | args.SigningToolPath,\r | |
394 | args.OpenSslSignerPrivateCertFile,\r | |
395 | args.OpenSslOtherPublicCertFile,\r | |
396 | args.OpenSslTrustedPublicCertFile\r | |
397 | )\r | |
398 | except:\r | |
399 | print ('GenerateCapsule: error: can not sign payload')\r | |
400 | raise\r | |
401 | sys.exit (1)\r | |
402 | \r | |
403 | try:\r | |
404 | FmpAuthHeader.MonotonicCount = args.MonotonicCount\r | |
405 | FmpAuthHeader.CertData = CertData\r | |
406 | FmpAuthHeader.Payload = Result\r | |
407 | Result = FmpAuthHeader.Encode ()\r | |
408 | if args.Verbose:\r | |
409 | FmpAuthHeader.DumpInfo ()\r | |
410 | except:\r | |
411 | print ('GenerateCapsule: error: can not encode FMP Auth Header')\r | |
412 | sys.exit (1)\r | |
413 | \r | |
414 | try:\r | |
415 | FmpCapsuleHeader.AddPayload (args.Guid, Result, HardwareInstance = args.HardwareInstance)\r | |
416 | Result = FmpCapsuleHeader.Encode ()\r | |
417 | if args.Verbose:\r | |
418 | FmpCapsuleHeader.DumpInfo ()\r | |
419 | except:\r | |
420 | print ('GenerateCapsule: error: can not encode FMP Capsule Header')\r | |
421 | sys.exit (1)\r | |
422 | \r | |
423 | try:\r | |
424 | UefiCapsuleHeader.OemFlags = args.CapsuleOemFlag\r | |
425 | UefiCapsuleHeader.PersistAcrossReset = 'PersistAcrossReset' in args.CapsuleFlag\r | |
2779c222 | 426 | UefiCapsuleHeader.PopulateSystemTable = False\r |
8b63877a KM |
427 | UefiCapsuleHeader.InitiateReset = 'InitiateReset' in args.CapsuleFlag\r |
428 | UefiCapsuleHeader.Payload = Result\r | |
429 | Result = UefiCapsuleHeader.Encode ()\r | |
430 | if args.Verbose:\r | |
431 | UefiCapsuleHeader.DumpInfo ()\r | |
432 | except:\r | |
433 | print ('GenerateCapsule: error: can not encode UEFI Capsule Header')\r | |
434 | sys.exit (1)\r | |
435 | \r | |
436 | elif args.Decode:\r | |
437 | try:\r | |
438 | Result = UefiCapsuleHeader.Decode (Buffer)\r | |
439 | FmpCapsuleHeader.Decode (Result)\r | |
440 | Result = FmpCapsuleHeader.GetFmpCapsuleImageHeader (0).Payload\r | |
441 | if args.Verbose:\r | |
442 | print ('========')\r | |
443 | UefiCapsuleHeader.DumpInfo ()\r | |
444 | print ('--------')\r | |
445 | FmpCapsuleHeader.DumpInfo ()\r | |
446 | if UseSignTool or UseOpenSsl:\r | |
447 | Result = FmpAuthHeader.Decode (Result)\r | |
448 | \r | |
449 | #\r | |
450 | # Verify Image with 64-bit MonotonicCount appended to end of image\r | |
451 | #\r | |
452 | try:\r | |
453 | if UseSignTool:\r | |
454 | CertData = VerifyPayloadSignTool (\r | |
455 | FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),\r | |
456 | FmpAuthHeader.CertData,\r | |
457 | args.SigningToolPath,\r | |
458 | args.SignToolPfxFile\r | |
459 | )\r | |
460 | else:\r | |
461 | CertData = VerifyPayloadOpenSsl (\r | |
462 | FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),\r | |
463 | FmpAuthHeader.CertData,\r | |
464 | args.SigningToolPath,\r | |
465 | args.OpenSslSignerPrivateCertFile,\r | |
466 | args.OpenSslOtherPublicCertFile,\r | |
467 | args.OpenSslTrustedPublicCertFile\r | |
468 | )\r | |
469 | except ValueError:\r | |
470 | print ('GenerateCapsule: warning: can not verify payload.')\r | |
471 | \r | |
472 | Result = FmpPayloadHeader.Decode (Result)\r | |
473 | if args.Verbose:\r | |
474 | print ('--------')\r | |
475 | FmpAuthHeader.DumpInfo ()\r | |
476 | print ('--------')\r | |
477 | FmpPayloadHeader.DumpInfo ()\r | |
478 | else:\r | |
479 | if args.Verbose:\r | |
480 | print ('--------')\r | |
481 | print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')\r | |
482 | print ('--------')\r | |
483 | print ('No FMP_PAYLOAD_HEADER')\r | |
484 | if args.Verbose:\r | |
485 | print ('========')\r | |
486 | except:\r | |
487 | print ('GenerateCapsule: error: can not decode capsule')\r | |
488 | raise\r | |
489 | sys.exit (1)\r | |
490 | \r | |
491 | elif args.DumpInfo:\r | |
492 | try:\r | |
493 | Result = UefiCapsuleHeader.Decode (Buffer)\r | |
494 | FmpCapsuleHeader.Decode (Result)\r | |
495 | Result = FmpCapsuleHeader.GetFmpCapsuleImageHeader (0).Payload\r | |
496 | print ('========')\r | |
497 | UefiCapsuleHeader.DumpInfo ()\r | |
498 | print ('--------')\r | |
499 | FmpCapsuleHeader.DumpInfo ()\r | |
500 | try:\r | |
501 | Result = FmpAuthHeader.Decode (Result)\r | |
502 | Result = FmpPayloadHeader.Decode (Result)\r | |
503 | print ('--------')\r | |
504 | FmpAuthHeader.DumpInfo ()\r | |
505 | print ('--------')\r | |
506 | FmpPayloadHeader.DumpInfo ()\r | |
507 | except:\r | |
508 | print ('--------')\r | |
509 | print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')\r | |
510 | print ('--------')\r | |
511 | print ('No FMP_PAYLOAD_HEADER')\r | |
512 | print ('========')\r | |
513 | except:\r | |
514 | print ('GenerateCapsule: error: can not decode capsule')\r | |
515 | sys.exit (1)\r | |
516 | else:\r | |
517 | print('GenerateCapsule: error: invalid options')\r | |
518 | sys.exit (1)\r | |
519 | \r | |
520 | #\r | |
521 | # Write binary output file\r | |
522 | #\r | |
523 | if args.OutputFile is not None:\r | |
524 | try:\r | |
525 | if args.Verbose:\r | |
526 | print ('Write binary output file {File}'.format (File = args.OutputFile.name))\r | |
527 | args.OutputFile.write (Result)\r | |
528 | args.OutputFile.close ()\r | |
529 | except:\r | |
530 | print ('GenerateCapsule: error: can not write binary output file {File}'.format (File = args.OutputFile.name))\r | |
531 | sys.exit (1)\r | |
532 | \r | |
533 | if args.Verbose:\r | |
534 | print('Success')\r |