]> git.proxmox.com Git - mirror_edk2.git/commitdiff
BaseTools: FMP capsule add the support to generate auth info
authorYonghong Zhu <yonghong.zhu@intel.com>
Mon, 15 Aug 2016 05:52:12 +0000 (13:52 +0800)
committerYonghong Zhu <yonghong.zhu@intel.com>
Fri, 19 Aug 2016 07:37:59 +0000 (15:37 +0800)
Current BaseTools cannot generate EFI_FIRMWARE_IMAGE_AUTHENTICATION
for FMP capsule. this patch fix it by FDF spec's update to add the
definition for CERTIFICATE_GUID and  MONOTONIC_COUNT. BaseTools call
the tool by CERTIFICATE_GUID to generate the certdata and fill the header
info.

Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
BaseTools/Source/Python/GenFds/Capsule.py
BaseTools/Source/Python/GenFds/CapsuleData.py
BaseTools/Source/Python/GenFds/FdfParser.py
BaseTools/Source/Python/GenFds/GenFds.py
BaseTools/Source/Python/GenFds/GuidSection.py

index 1683433e43429065a5e36be7e7b1410833a9ab4e..f8af12a7c27afbeabbc27f38bc01ab7797320d74 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # generate capsule\r
 #\r
-#  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -25,9 +25,16 @@ from GenFds import GenFds
 from Common.Misc import PackRegistryFormatGuid\r
 import uuid\r
 from struct import pack\r
+from GenFds import FindExtendTool\r
+from Common import EdkLogger\r
+from Common.BuildToolError import *\r
 \r
 \r
 T_CHAR_LF = '\n'\r
+WIN_CERT_REVISION      = 0x0200\r
+WIN_CERT_TYPE_EFI_GUID = 0x0EF1\r
+EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID('{4aafd29d-68df-49ee-8aa9-347d375665a7}')\r
+EFI_CERT_TYPE_RSA2048_SHA256_GUID = uuid.UUID('{a7717414-c616-4977-9420-844712a735bf}')\r
 \r
 ## create inf file describes what goes into capsule and call GenFv to generate capsule\r
 #\r
@@ -98,6 +105,32 @@ class Capsule (CapsuleClassObject) :
         FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList), len(self.FmpPayloadList)))\r
         FwMgrHdrSize = 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList))\r
 \r
+        #\r
+        # typedef struct _WIN_CERTIFICATE {\r
+        #   UINT32 dwLength;\r
+        #   UINT16 wRevision;\r
+        #   UINT16 wCertificateType;\r
+        # //UINT8 bCertificate[ANYSIZE_ARRAY];\r
+        # } WIN_CERTIFICATE;\r
+        #\r
+        # typedef struct _WIN_CERTIFICATE_UEFI_GUID {\r
+        #   WIN_CERTIFICATE Hdr;\r
+        #   EFI_GUID        CertType;\r
+        # //UINT8 CertData[ANYSIZE_ARRAY];\r
+        # } WIN_CERTIFICATE_UEFI_GUID;\r
+        #\r
+        # typedef struct {\r
+        #   UINT64                    MonotonicCount;\r
+        #   WIN_CERTIFICATE_UEFI_GUID AuthInfo;\r
+        # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;\r
+        #\r
+        # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {\r
+        #   EFI_GUID HashType;\r
+        #   UINT8 PublicKey[256];\r
+        #   UINT8 Signature[256];\r
+        # } EFI_CERT_BLOCK_RSA_2048_SHA256;\r
+        #\r
+\r
         PreSize = FwMgrHdrSize\r
         Content = StringIO.StringIO()\r
         for driver in self.CapsuleDataList:\r
@@ -108,10 +141,47 @@ class Capsule (CapsuleClassObject) :
             Content.write(File.read())\r
             File.close()\r
         for fmp in self.FmpPayloadList:\r
-            payload = fmp.GenCapsuleSubItem()\r
-            FwMgrHdr.write(pack('=Q', PreSize))\r
-            PreSize += len(payload)\r
-            Content.write(payload)\r
+            if fmp.Certificate_Guid:\r
+                ExternalTool, ExternalOption = FindExtendTool([], GenFdsGlobalVariable.ArchList, fmp.Certificate_Guid)\r
+                CmdOption = ''\r
+                CapInputFile = fmp.ImageFile\r
+                if not os.path.isabs(fmp.ImageFile):\r
+                    CapInputFile = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, fmp.ImageFile)\r
+                CapOutputTmp = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.tmp'\r
+                if ExternalTool == None:\r
+                    EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % fmp.Certificate_Guid)\r
+                else:\r
+                    CmdOption += ExternalTool\r
+                if ExternalOption:\r
+                    CmdOption = CmdOption + ' ' + ExternalOption\r
+                CmdOption += ' -e ' + ' --monotonic-count ' + str(fmp.MonotonicCount) + ' -o ' + CapOutputTmp + ' ' + CapInputFile\r
+                CmdList = CmdOption.split()\r
+                GenFdsGlobalVariable.CallExternalTool(CmdList, "Failed to generate FMP auth capsule")\r
+                if uuid.UUID(fmp.Certificate_Guid) == EFI_CERT_TYPE_PKCS7_GUID:\r
+                    dwLength = 4 + 2 + 2 + 16 + os.path.getsize(CapOutputTmp) - os.path.getsize(CapInputFile)\r
+                else:\r
+                    dwLength = 4 + 2 + 2 + 16 + 16 + 256 + 256\r
+                Buffer  = pack('Q', fmp.MonotonicCount)\r
+                Buffer += pack('I', dwLength)\r
+                Buffer += pack('H', WIN_CERT_REVISION)\r
+                Buffer += pack('H', WIN_CERT_TYPE_EFI_GUID)\r
+                Buffer += uuid.UUID(fmp.Certificate_Guid).get_bytes_le()\r
+                if os.path.exists(CapOutputTmp):\r
+                    TmpFile = open(CapOutputTmp, 'rb')\r
+                    Buffer += TmpFile.read()\r
+                    TmpFile.close()\r
+                    if fmp.VendorCodeFile:\r
+                        VendorFile = open(fmp.VendorCodeFile, 'rb')\r
+                        Buffer += VendorFile.read()\r
+                        VendorFile.close()\r
+                    FwMgrHdr.write(pack('=Q', PreSize))\r
+                    PreSize += len(Buffer)\r
+                    Content.write(Buffer)\r
+            else:\r
+                payload = fmp.GenCapsuleSubItem()\r
+                FwMgrHdr.write(pack('=Q', PreSize))\r
+                PreSize += len(payload)\r
+                Content.write(payload)\r
         BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue())\r
         Header.write(pack('=I', HdrSize + BodySize))\r
         #\r
index efc281222bd585b19d4a9dc4fc2a3d6635aa376b..2a5c4545de9f88b8ae1773ea0f264fcbb09540d5 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # generate capsule\r
 #\r
-#  Copyright (c) 2007-2013, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2007-2016, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -180,6 +180,8 @@ class CapsulePayload(CapsuleData):
         self.HardwareInstance = None\r
         self.ImageFile = None\r
         self.VendorCodeFile = None\r
+        self.Certificate_Guid = None\r
+        self.MonotonicCount = None\r
 \r
     def GenCapsuleSubItem(self):\r
         if not self.Version:\r
index 8709cfc0917860a0391cd5ab73a005a94b2953a7..02ae7c9f9c6bc6bfa4a078c4c84107b27a2e7734 100644 (file)
@@ -52,11 +52,13 @@ import Common.GlobalData as GlobalData
 from Common.Expression import *\r
 from Common import GlobalData\r
 from Common.String import ReplaceMacro\r
-\r
+import uuid\r
 from Common.Misc import tdict\r
 \r
 import Common.LongFilePathOs as os\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
+from Capsule import EFI_CERT_TYPE_PKCS7_GUID\r
+from Capsule import EFI_CERT_TYPE_RSA2048_SHA256_GUID\r
 \r
 ##define T_CHAR_SPACE                ' '\r
 ##define T_CHAR_NULL                 '\0'\r
@@ -1124,6 +1126,26 @@ class FdfParser:
             self.__UndoToken()\r
             return False\r
 \r
+    def __Verify(self, Name, Value, Scope):\r
+        if Scope in ['UINT64', 'UINT8']:\r
+            ValueNumber = 0\r
+            try:\r
+                if Value.upper().startswith('0X'):\r
+                    ValueNumber = int (Value, 16)\r
+                else:\r
+                    ValueNumber = int (Value)\r
+            except:\r
+                EdkLogger.error("FdfParser", FORMAT_INVALID, "The value is not valid dec or hex number for %s." % Name)\r
+            if ValueNumber < 0:\r
+                EdkLogger.error("FdfParser", FORMAT_INVALID, "The value can't be set to negative value for %s." % Name)\r
+            if Scope == 'UINT64':\r
+                if ValueNumber >= 0x10000000000000000:\r
+                    EdkLogger.error("FdfParser", FORMAT_INVALID, "Too large value for %s." % Name)\r
+            if Scope == 'UINT8':\r
+                if ValueNumber >= 0x100:\r
+                    EdkLogger.error("FdfParser", FORMAT_INVALID, "Too large value for %s." % Name)\r
+            return True\r
+\r
     ## __UndoToken() method\r
     #\r
     #   Go back one token unit in file buffer\r
@@ -3187,7 +3209,7 @@ class FdfParser:
 \r
         if not self.__GetNextToken():\r
             raise Warning("The FMP payload section is empty!", self.FileName, self.CurrentLineNumber)\r
-        FmpKeyList = ['IMAGE_HEADER_INIT_VERSION', 'IMAGE_TYPE_ID', 'IMAGE_INDEX', 'HARDWARE_INSTANCE']\r
+        FmpKeyList = ['IMAGE_HEADER_INIT_VERSION', 'IMAGE_TYPE_ID', 'IMAGE_INDEX', 'HARDWARE_INSTANCE', 'CERTIFICATE_GUID', 'MONOTONIC_COUNT']\r
         while self.__Token in FmpKeyList:\r
             Name = self.__Token\r
             FmpKeyList.remove(Name)\r
@@ -3195,32 +3217,58 @@ class FdfParser:
                 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)\r
             if Name == 'IMAGE_TYPE_ID':\r
                 if not self.__GetNextGuid():\r
-                    raise Warning("expected GUID value for IMAGE_TYPE_ID", self.FileName, self.CurrentLineNumber)\r
+                    raise Warning("expected GUID value for IMAGE_TYPE_ID.", self.FileName, self.CurrentLineNumber)\r
                 FmpData.ImageTypeId = self.__Token\r
+            elif Name == 'CERTIFICATE_GUID':\r
+                if not self.__GetNextGuid():\r
+                    raise Warning("expected GUID value for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)\r
+                FmpData.Certificate_Guid = self.__Token\r
+                if uuid.UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_RSA2048_SHA256_GUID and uuid.UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_PKCS7_GUID:\r
+                    raise Warning("Only support EFI_CERT_TYPE_RSA2048_SHA256_GUID or EFI_CERT_TYPE_PKCS7_GUID for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)\r
             else:\r
                 if not self.__GetNextToken():\r
                     raise Warning("expected value of %s" % Name, self.FileName, self.CurrentLineNumber)\r
                 Value = self.__Token\r
                 if Name == 'IMAGE_HEADER_INIT_VERSION':\r
-                    FmpData.Version = Value\r
+                    if self.__Verify(Name, Value, 'UINT8'):\r
+                        FmpData.Version = Value\r
                 elif Name == 'IMAGE_INDEX':\r
-                    FmpData.ImageIndex = Value\r
+                    if self.__Verify(Name, Value, 'UINT8'):\r
+                        FmpData.ImageIndex = Value\r
                 elif Name == 'HARDWARE_INSTANCE':\r
-                    FmpData.HardwareInstance = Value\r
+                    if self.__Verify(Name, Value, 'UINT8'):\r
+                        FmpData.HardwareInstance = Value\r
+                elif Name == 'MONOTONIC_COUNT':\r
+                    if self.__Verify(Name, Value, 'UINT64'):\r
+                        FmpData.MonotonicCount = Value\r
+                        if FmpData.MonotonicCount.upper().startswith('0X'):\r
+                            FmpData.MonotonicCount = (long)(FmpData.MonotonicCount, 16)\r
+                        else:\r
+                            FmpData.MonotonicCount = (long)(FmpData.MonotonicCount)\r
             if not self.__GetNextToken():\r
                 break\r
         else:\r
             self.__UndoToken()\r
 \r
+        if (FmpData.MonotonicCount and not FmpData.Certificate_Guid) or (not FmpData.MonotonicCount and FmpData.Certificate_Guid):\r
+            EdkLogger.error("FdfParser", FORMAT_INVALID, "CERTIFICATE_GUID and MONOTONIC_COUNT must be work as a pair.")\r
+        # remove CERTIFICATE_GUID and MONOTONIC_COUNT from FmpKeyList, since these keys are optional\r
+        if 'CERTIFICATE_GUID' in FmpKeyList:\r
+            FmpKeyList.remove('CERTIFICATE_GUID')\r
+        if 'MONOTONIC_COUNT' in FmpKeyList:\r
+            FmpKeyList.remove('MONOTONIC_COUNT')\r
         if FmpKeyList:\r
-            raise Warning("Missing keywords %s in FMP payload section" % ', '.join(FmpKeyList), self.FileName, self.CurrentLineNumber)\r
+            raise Warning("Missing keywords %s in FMP payload section." % ', '.join(FmpKeyList), self.FileName, self.CurrentLineNumber)\r
         ImageFile = self.__ParseRawFileStatement()\r
         if not ImageFile:\r
-            raise Warning("Missing image file in FMP payload section", self.FileName, self.CurrentLineNumber)\r
+            raise Warning("Missing image file in FMP payload section.", self.FileName, self.CurrentLineNumber)\r
         FmpData.ImageFile = ImageFile\r
         VendorCodeFile = self.__ParseRawFileStatement()\r
         if VendorCodeFile:\r
             FmpData.VendorCodeFile = VendorCodeFile\r
+        AdditionalFile = self.__ParseRawFileStatement()\r
+        if AdditionalFile:\r
+            raise Warning("At most one Image file and one Vendor code file are allowed in FMP payload section.", self.FileName, self.CurrentLineNumber)\r
         self.Profile.FmpPayloadDict[FmpUiName] = FmpData\r
         return True\r
 \r
index f2de47ea83e66eed02471ddaaeb7b25ab28b5f23..c2e9418b84caaa219e08fb257fd5cd797a1538ee 100644 (file)
@@ -415,7 +415,64 @@ def BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, Val
             Value = '0'\r
     return  Value\r
 \r
-        \r
+## FindExtendTool()\r
+#\r
+#  Find location of tools to process data\r
+#\r
+#  @param  KeyStringList    Filter for inputs of section generation\r
+#  @param  CurrentArchList  Arch list\r
+#  @param  NameGuid         The Guid name\r
+#\r
+def FindExtendTool(KeyStringList, CurrentArchList, NameGuid):\r
+    # if user not specify filter, try to deduce it from global data.\r
+    if KeyStringList == None or KeyStringList == []:\r
+        Target = GenFdsGlobalVariable.TargetName\r
+        ToolChain = GenFdsGlobalVariable.ToolChainTag\r
+        ToolDb = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDatabase\r
+        if ToolChain not in ToolDb['TOOL_CHAIN_TAG']:\r
+            EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain)\r
+        KeyStringList = [Target + '_' + ToolChain + '_' + CurrentArchList[0]]\r
+        for Arch in CurrentArchList:\r
+            if Target + '_' + ToolChain + '_' + Arch not in KeyStringList:\r
+                KeyStringList.append(Target + '_' + ToolChain + '_' + Arch)\r
+\r
+    if GenFdsGlobalVariable.GuidToolDefinition:\r
+        if NameGuid in GenFdsGlobalVariable.GuidToolDefinition.keys():\r
+            return GenFdsGlobalVariable.GuidToolDefinition[NameGuid]\r
+\r
+    ToolDefinition = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDictionary\r
+    ToolPathTmp = None\r
+    ToolOption = None\r
+    for ToolDef in ToolDefinition.items():\r
+        if NameGuid == ToolDef[1]:\r
+            KeyList = ToolDef[0].split('_')\r
+            Key = KeyList[0] + \\r
+                  '_' + \\r
+                  KeyList[1] + \\r
+                  '_' + \\r
+                  KeyList[2]\r
+            if Key in KeyStringList and KeyList[4] == 'GUID':\r
+\r
+                ToolPath = ToolDefinition.get(Key + \\r
+                                               '_' + \\r
+                                               KeyList[3] + \\r
+                                               '_' + \\r
+                                               'PATH')\r
+\r
+                ToolOption = ToolDefinition.get(Key + \\r
+                                                '_' + \\r
+                                                KeyList[3] + \\r
+                                                '_' + \\r
+                                                'FLAGS')\r
+                if ToolPathTmp == None:\r
+                    ToolPathTmp = ToolPath\r
+                else:\r
+                    if ToolPathTmp != ToolPath:\r
+                        EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath))\r
+\r
+    GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption)\r
+    return ToolPathTmp, ToolOption\r
+\r
 ## Parse command line options\r
 #\r
 # Using standard Python module optparse to parse command line option of this tool.\r
index ac5ae585f90f437f9b929f795c2cae3c3d75a46e..f199dcd2ccc11ad6d2df5dd612f50f499ee435e7 100644 (file)
@@ -27,6 +27,7 @@ from Common import EdkLogger
 from Common.BuildToolError import *\r
 from FvImageSection import FvImageSection\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
+from GenFds import FindExtendTool\r
 \r
 ## generate GUIDed section\r
 #\r
@@ -128,7 +129,7 @@ class GuidSection(GuidSectionClassObject) :
         ExternalTool = None\r
         ExternalOption = None\r
         if self.NameGuid != None:\r
-            ExternalTool, ExternalOption = self.__FindExtendTool__()\r
+            ExternalTool, ExternalOption = FindExtendTool(self.KeyStringList, self.CurrentArchList, self.NameGuid)\r
 \r
         #\r
         # If not have GUID , call default\r
@@ -249,61 +250,5 @@ class GuidSection(GuidSectionClassObject) :
                 self.ProcessRequired = "TRUE"\r
             return OutputFileList, self.Alignment\r
 \r
-    ## __FindExtendTool()\r
-    #\r
-    #    Find location of tools to process section data\r
-    #\r
-    #   @param  self        The object pointer\r
-    #\r
-    def __FindExtendTool__(self):\r
-        # if user not specify filter, try to deduce it from global data.\r
-        if self.KeyStringList == None or self.KeyStringList == []:\r
-            Target = GenFdsGlobalVariable.TargetName\r
-            ToolChain = GenFdsGlobalVariable.ToolChainTag\r
-            ToolDb = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDatabase\r
-            if ToolChain not in ToolDb['TOOL_CHAIN_TAG']:\r
-                EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain)\r
-            self.KeyStringList = [Target + '_' + ToolChain + '_' + self.CurrentArchList[0]]\r
-            for Arch in self.CurrentArchList:\r
-                if Target + '_' + ToolChain + '_' + Arch not in self.KeyStringList:\r
-                    self.KeyStringList.append(Target + '_' + ToolChain + '_' + Arch)\r
-\r
-        if GenFdsGlobalVariable.GuidToolDefinition:\r
-            if self.NameGuid in GenFdsGlobalVariable.GuidToolDefinition.keys():\r
-                return GenFdsGlobalVariable.GuidToolDefinition[self.NameGuid]\r
-\r
-        ToolDefinition = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDictionary\r
-        ToolPathTmp = None\r
-        ToolOption = None\r
-        for ToolDef in ToolDefinition.items():\r
-            if self.NameGuid == ToolDef[1]:\r
-                KeyList = ToolDef[0].split('_')\r
-                Key = KeyList[0] + \\r
-                      '_' + \\r
-                      KeyList[1] + \\r
-                      '_' + \\r
-                      KeyList[2]\r
-                if Key in self.KeyStringList and KeyList[4] == 'GUID':\r
-\r
-                    ToolPath = ToolDefinition.get(Key + \\r
-                                                   '_' + \\r
-                                                   KeyList[3] + \\r
-                                                   '_' + \\r
-                                                   'PATH')\r
-\r
-                    ToolOption = ToolDefinition.get(Key + \\r
-                                                    '_' + \\r
-                                                    KeyList[3] + \\r
-                                                    '_' + \\r
-                                                    'FLAGS')\r
-                    if ToolPathTmp == None:\r
-                        ToolPathTmp = ToolPath\r
-                    else:\r
-                        if ToolPathTmp != ToolPath:\r
-                            EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath))\r
-\r
-        GenFdsGlobalVariable.GuidToolDefinition[self.NameGuid] = (ToolPathTmp, ToolOption)\r
-        return ToolPathTmp, ToolOption\r
-\r
 \r
 \r