]> git.proxmox.com Git - mirror_edk2.git/commitdiff
SecurityPkg: Add constraints on PK strength
authorJiaqi Gao <jiaqi.gao@intel.com>
Mon, 26 Apr 2021 04:31:15 +0000 (12:31 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 26 Apr 2021 16:24:32 +0000 (16:24 +0000)
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3293

Add constraints on the key strength of enrolled platform key(PK), which
must be greater than or equal to 2048 bit. PK key strength is required
by Intel SDL and MSFT, etc. This limitation prevents user from using
weak keys as PK.

The original code to check the certificate file type is placed in a new
function CheckX509Certificate(), which checks if the X.509 certificate
meets the requirements of encode type, RSA-Key strengh, etc.

Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Jiaqi Gao <jiaqi.gao@intel.com>
Reviewed-by: Min Xu <min.m.xu@intel.com>
Acked-by: Jiewen Yao <jiewen.yao@intel.com>
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h

index 4f01a2ed677e8813b845ce3f054a9078cf293430..e82bfe77570de0960daa8fb2e0a226ac44cbf55a 100644 (file)
@@ -90,6 +90,22 @@ CHAR16* mDerEncodedSuffix[] = {
 };\r
 CHAR16* mSupportX509Suffix = L"*.cer/der/crt";\r
 \r
+//\r
+// Prompt strings during certificate enrollment.\r
+//\r
+CHAR16* mX509EnrollPromptTitle[] = {\r
+  L"",\r
+  L"ERROR: Unsupported file type!",\r
+  L"ERROR: Unsupported certificate!",\r
+  NULL\r
+};\r
+CHAR16* mX509EnrollPromptString[] = {\r
+  L"",\r
+  L"Only DER encoded certificate file (*.cer/der/crt) is supported.",\r
+  L"Public key length should be equal to or greater than 2048 bits.",\r
+  NULL\r
+};\r
+\r
 SECUREBOOT_CONFIG_PRIVATE_DATA  *gSecureBootPrivateData = NULL;\r
 \r
 /**\r
@@ -383,6 +399,102 @@ SetSecureBootMode (
                 );\r
 }\r
 \r
+/**\r
+  This code checks if the encode type and key strength of X.509\r
+  certificate is qualified.\r
+\r
+  @param[in]  X509FileContext     FileContext of X.509 certificate storing\r
+                                  file.\r
+  @param[out] Error               Error type checked in the certificate.\r
+\r
+  @return EFI_SUCCESS             The certificate checked successfully.\r
+  @return EFI_INVALID_PARAMETER   The parameter is invalid.\r
+  @return EFI_OUT_OF_RESOURCES    Memory allocation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+CheckX509Certificate (\r
+  IN    SECUREBOOT_FILE_CONTEXT*    X509FileContext,\r
+  OUT   ENROLL_KEY_ERROR*           Error\r
+)\r
+{\r
+  EFI_STATUS     Status;\r
+  UINT16*        FilePostFix;\r
+  UINTN          NameLength;\r
+  UINT8*         X509Data;\r
+  UINTN          X509DataSize;\r
+  void*          X509PubKey;\r
+  UINTN          PubKeyModSize;\r
+\r
+  if (X509FileContext->FileName == NULL) {\r
+    *Error = Unsupported_Type;\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  X509Data       = NULL;\r
+  X509DataSize   = 0;\r
+  X509PubKey     = NULL;\r
+  PubKeyModSize  = 0;\r
+\r
+  //\r
+  // Parse the file's postfix. Only support DER encoded X.509 certificate files.\r
+  //\r
+  NameLength = StrLen (X509FileContext->FileName);\r
+  if (NameLength <= 4) {\r
+    DEBUG ((DEBUG_ERROR, "Wrong X509 NameLength\n"));\r
+    *Error = Unsupported_Type;\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  FilePostFix = X509FileContext->FileName + NameLength - 4;\r
+  if (!IsDerEncodeCertificate (FilePostFix)) {\r
+    DEBUG ((DEBUG_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.\n", mSupportX509Suffix));\r
+    *Error = Unsupported_Type;\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  DEBUG ((DEBUG_INFO, "FileName= %s\n", X509FileContext->FileName));\r
+  DEBUG ((DEBUG_INFO, "FilePostFix = %s\n", FilePostFix));\r
+\r
+  //\r
+  // Read the certificate file content\r
+  //\r
+  Status = ReadFileContent (X509FileContext->FHandle, (VOID**) &X509Data, &X509DataSize, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Error occured while reading the file.\n"));\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Parse the public key context.\r
+  //\r
+  if (RsaGetPublicKeyFromX509 (X509Data, X509DataSize, &X509PubKey) == FALSE) {\r
+    DEBUG ((DEBUG_ERROR, "Error occured while parsing the pubkey from certificate.\n"));\r
+    Status = EFI_INVALID_PARAMETER;\r
+    *Error = Unsupported_Type;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Parse Module size of public key using interface provided by CryptoPkg, which is\r
+  // actually the size of public key.\r
+  //\r
+  if (X509PubKey != NULL) {\r
+    RsaGetKey (X509PubKey, RsaKeyN, NULL, &PubKeyModSize);\r
+    if (PubKeyModSize < CER_PUBKEY_MIN_SIZE) {\r
+      DEBUG ((DEBUG_ERROR, "Unqualified PK size, key size should be equal to or greater than 2048 bits.\n"));\r
+      Status = EFI_INVALID_PARAMETER;\r
+      *Error = Unqualified_Key;\r
+    }\r
+    RsaFree (X509PubKey);\r
+  }\r
+\r
+ ON_EXIT:\r
+  if (X509Data != NULL) {\r
+    FreePool (X509Data);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   Generate the PK signature list from the X509 Certificate storing file (.cer)\r
 \r
@@ -477,12 +589,6 @@ EnrollPlatformKey (
   UINT32                          Attr;\r
   UINTN                           DataSize;\r
   EFI_SIGNATURE_LIST              *PkCert;\r
-  UINT16*                         FilePostFix;\r
-  UINTN                           NameLength;\r
-\r
-  if (Private->FileContext->FileName == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
 \r
   PkCert = NULL;\r
 \r
@@ -491,21 +597,6 @@ EnrollPlatformKey (
     return Status;\r
   }\r
 \r
-  //\r
-  // Parse the file's postfix. Only support DER encoded X.509 certificate files.\r
-  //\r
-  NameLength = StrLen (Private->FileContext->FileName);\r
-  if (NameLength <= 4) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
-  if (!IsDerEncodeCertificate(FilePostFix)) {\r
-    DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix));\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  DEBUG ((EFI_D_INFO, "FileName= %s\n", Private->FileContext->FileName));\r
-  DEBUG ((EFI_D_INFO, "FilePostFix = %s\n", FilePostFix));\r
-\r
   //\r
   // Prase the selected PK file and generate PK certificate list.\r
   //\r
@@ -4300,12 +4391,14 @@ SecureBootCallback (
   UINT16                          *FilePostFix;\r
   SECUREBOOT_CONFIG_PRIVATE_DATA  *PrivateData;\r
   BOOLEAN                         GetBrowserDataResult;\r
+  ENROLL_KEY_ERROR                EnrollKeyErrorCode;\r
 \r
-  Status           = EFI_SUCCESS;\r
-  SecureBootEnable = NULL;\r
-  SecureBootMode   = NULL;\r
-  SetupMode        = NULL;\r
-  File             = NULL;\r
+  Status             = EFI_SUCCESS;\r
+  SecureBootEnable   = NULL;\r
+  SecureBootMode     = NULL;\r
+  SetupMode          = NULL;\r
+  File               = NULL;\r
+  EnrollKeyErrorCode = None_Error;\r
 \r
   if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -4718,18 +4811,35 @@ SecureBootCallback (
       }\r
       break;\r
     case KEY_VALUE_SAVE_AND_EXIT_PK:\r
-      Status = EnrollPlatformKey (Private);\r
+      //\r
+      // Check the suffix, encode type and the key strength of PK certificate.\r
+      //\r
+      Status = CheckX509Certificate (Private->FileContext, &EnrollKeyErrorCode);\r
+      if (EFI_ERROR (Status)) {\r
+        if (EnrollKeyErrorCode != None_Error && EnrollKeyErrorCode < Enroll_Error_Max) {\r
+          CreatePopUp (\r
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+            &Key,\r
+            mX509EnrollPromptTitle[EnrollKeyErrorCode],\r
+            mX509EnrollPromptString[EnrollKeyErrorCode],\r
+            NULL\r
+            );\r
+          break;\r
+        }\r
+      } else {\r
+        Status = EnrollPlatformKey (Private);\r
+      }\r
       if (EFI_ERROR (Status)) {\r
         UnicodeSPrint (\r
           PromptString,\r
           sizeof (PromptString),\r
-          L"Only DER encoded certificate file (%s) is supported.",\r
-          mSupportX509Suffix\r
+          L"Error status: %x.",\r
+          Status\r
           );\r
         CreatePopUp (\r
           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
           &Key,\r
-          L"ERROR: Unsupported file type!",\r
+          L"ERROR: Enrollment failed!",\r
           PromptString,\r
           NULL\r
           );\r
index 1fafae07ac2a61912a76743ef22ebff83e78b472..268f015e8e7dabe71031c79fc22a665b9a202ed2 100644 (file)
@@ -93,6 +93,27 @@ extern  EFI_IFR_GUID_LABEL         *mEndLabel;
 #define HASHALG_RAW                            0x00000004\r
 #define HASHALG_MAX                            0x00000004\r
 \r
+//\r
+// Certificate public key minimum size (bytes)\r
+//\r
+#define CER_PUBKEY_MIN_SIZE     256\r
+\r
+//\r
+// Types of errors may occur during certificate enrollment.\r
+//\r
+typedef enum {\r
+  None_Error = 0,\r
+  //\r
+  // Unsupported_type indicates the certificate type is not supported.\r
+  //\r
+  Unsupported_Type,\r
+  //\r
+  // Unqualified_key indicates the key strength of certificate is not\r
+  // strong enough.\r
+  //\r
+  Unqualified_Key,\r
+  Enroll_Error_Max\r
+}ENROLL_KEY_ERROR;\r
 \r
 typedef struct {\r
   UINTN             Signature;\r