| ## @file | |
| # Module that encodes and decodes a EFI_FIRMWARE_IMAGE_AUTHENTICATION with | |
| # certificate data and payload data. | |
| # | |
| # Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR> | |
| # SPDX-License-Identifier: BSD-2-Clause-Patent | |
| # | |
| ''' | |
| FmpAuthHeader | |
| ''' | |
| import struct | |
| import uuid | |
| class FmpAuthHeaderClass (object): | |
| # /// | |
| # /// Image Attribute -Authentication Required | |
| # /// | |
| # typedef struct { | |
| # /// | |
| # /// It is included in the signature of AuthInfo. It is used to ensure freshness/no replay. | |
| # /// It is incremented during each firmware image operation. | |
| # /// | |
| # UINT64 MonotonicCount; | |
| # /// | |
| # /// Provides the authorization for the firmware image operations. It is a signature across | |
| # /// the image data and the Monotonic Count value. Caller uses the private key that is | |
| # /// associated with a public key that has been provisioned via the key exchange. | |
| # /// Because this is defined as a signature, WIN_CERTIFICATE_UEFI_GUID.CertType must | |
| # /// be EFI_CERT_TYPE_PKCS7_GUID. | |
| # /// | |
| # WIN_CERTIFICATE_UEFI_GUID AuthInfo; | |
| # } EFI_FIRMWARE_IMAGE_AUTHENTICATION; | |
| # | |
| # /// | |
| # /// Certificate which encapsulates a GUID-specific digital signature | |
| # /// | |
| # typedef struct { | |
| # /// | |
| # /// This is the standard WIN_CERTIFICATE header, where | |
| # /// wCertificateType is set to WIN_CERT_TYPE_EFI_GUID. | |
| # /// | |
| # WIN_CERTIFICATE Hdr; | |
| # /// | |
| # /// This is the unique id which determines the | |
| # /// format of the CertData. . | |
| # /// | |
| # EFI_GUID CertType; | |
| # /// | |
| # /// The following is the certificate data. The format of | |
| # /// the data is determined by the CertType. | |
| # /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID, | |
| # /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure. | |
| # /// | |
| # UINT8 CertData[1]; | |
| # } WIN_CERTIFICATE_UEFI_GUID; | |
| # | |
| # /// | |
| # /// The WIN_CERTIFICATE structure is part of the PE/COFF specification. | |
| # /// | |
| # typedef struct { | |
| # /// | |
| # /// The length of the entire certificate, | |
| # /// including the length of the header, in bytes. | |
| # /// | |
| # UINT32 dwLength; | |
| # /// | |
| # /// The revision level of the WIN_CERTIFICATE | |
| # /// structure. The current revision level is 0x0200. | |
| # /// | |
| # UINT16 wRevision; | |
| # /// | |
| # /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI | |
| # /// certificate types. The UEFI specification reserves the range of | |
| # /// certificate type values from 0x0EF0 to 0x0EFF. | |
| # /// | |
| # UINT16 wCertificateType; | |
| # /// | |
| # /// The following is the actual certificate. The format of | |
| # /// the certificate depends on wCertificateType. | |
| # /// | |
| # /// UINT8 bCertificate[ANYSIZE_ARRAY]; | |
| # /// | |
| # } WIN_CERTIFICATE; | |
| # | |
| # #define WIN_CERT_TYPE_EFI_GUID 0x0EF1 | |
| # | |
| # /// | |
| # /// This identifies a signature containing a DER-encoded PKCS #7 version 1.5 [RFC2315] | |
| # /// SignedData value. | |
| # /// | |
| # #define EFI_CERT_TYPE_PKCS7_GUID \ | |
| # { \ | |
| # 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} \ | |
| # } | |
| _StructFormat = '<QIHH16s' | |
| _StructSize = struct.calcsize (_StructFormat) | |
| _MonotonicCountFormat = '<Q' | |
| _MonotonicCountSize = struct.calcsize (_MonotonicCountFormat) | |
| _StructAuthInfoFormat = '<IHH16s' | |
| _StructAuthInfoSize = struct.calcsize (_StructAuthInfoFormat) | |
| _WIN_CERT_REVISION = 0x0200 | |
| _WIN_CERT_TYPE_EFI_GUID = 0x0EF1 | |
| _EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID ('4aafd29d-68df-49ee-8aa9-347d375665a7') | |
| def __init__ (self): | |
| self._Valid = False | |
| self.MonotonicCount = 0 | |
| self.dwLength = self._StructAuthInfoSize | |
| self.wRevision = self._WIN_CERT_REVISION | |
| self.wCertificateType = self._WIN_CERT_TYPE_EFI_GUID | |
| self.CertType = self._EFI_CERT_TYPE_PKCS7_GUID | |
| self.CertData = b'' | |
| self.Payload = b'' | |
| def Encode (self): | |
| if self.wRevision != self._WIN_CERT_REVISION: | |
| raise ValueError | |
| if self.wCertificateType != self._WIN_CERT_TYPE_EFI_GUID: | |
| raise ValueError | |
| if self.CertType != self._EFI_CERT_TYPE_PKCS7_GUID: | |
| raise ValueError | |
| self.dwLength = self._StructAuthInfoSize + len (self.CertData) | |
| FmpAuthHeader = struct.pack ( | |
| self._StructFormat, | |
| self.MonotonicCount, | |
| self.dwLength, | |
| self.wRevision, | |
| self.wCertificateType, | |
| self.CertType.bytes_le | |
| ) | |
| self._Valid = True | |
| return FmpAuthHeader + self.CertData + self.Payload | |
| def Decode (self, Buffer): | |
| if len (Buffer) < self._StructSize: | |
| raise ValueError | |
| (MonotonicCount, dwLength, wRevision, wCertificateType, CertType) = \ | |
| struct.unpack ( | |
| self._StructFormat, | |
| Buffer[0:self._StructSize] | |
| ) | |
| if dwLength < self._StructAuthInfoSize: | |
| raise ValueError | |
| if wRevision != self._WIN_CERT_REVISION: | |
| raise ValueError | |
| if wCertificateType != self._WIN_CERT_TYPE_EFI_GUID: | |
| raise ValueError | |
| if CertType != self._EFI_CERT_TYPE_PKCS7_GUID.bytes_le: | |
| raise ValueError | |
| self.MonotonicCount = MonotonicCount | |
| self.dwLength = dwLength | |
| self.wRevision = wRevision | |
| self.wCertificateType = wCertificateType | |
| self.CertType = uuid.UUID (bytes_le = CertType) | |
| self.CertData = Buffer[self._StructSize:self._MonotonicCountSize + self.dwLength] | |
| self.Payload = Buffer[self._MonotonicCountSize + self.dwLength:] | |
| self._Valid = True | |
| return self.Payload | |
| def IsSigned (self, Buffer): | |
| if len (Buffer) < self._StructSize: | |
| return False | |
| (MonotonicCount, dwLength, wRevision, wCertificateType, CertType) = \ | |
| struct.unpack ( | |
| self._StructFormat, | |
| Buffer[0:self._StructSize] | |
| ) | |
| if CertType != self._EFI_CERT_TYPE_PKCS7_GUID.bytes_le: | |
| return False | |
| return True | |
| def DumpInfo (self): | |
| if not self._Valid: | |
| raise ValueError | |
| print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.MonotonicCount = {MonotonicCount:016X}'.format (MonotonicCount = self.MonotonicCount)) | |
| print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.dwLength = {dwLength:08X}'.format (dwLength = self.dwLength)) | |
| print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wRevision = {wRevision:04X}'.format (wRevision = self.wRevision)) | |
| print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wCertificateType = {wCertificateType:04X}'.format (wCertificateType = self.wCertificateType)) | |
| print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertType = {Guid}'.format (Guid = str(self.CertType).upper())) | |
| print ('sizeof (EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertData) = {Size:08X}'.format (Size = len (self.CertData))) | |
| print ('sizeof (Payload) = {Size:08X}'.format (Size = len (self.Payload))) |