/** @file The secure boot variable function implementation. ;****************************************************************************** ;* Copyright (c) 2016 - 2021, Insyde Software Corp. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ #include "SecureBootVar.h" #define TAG_TYPE_VALUE_OID 0x06 /* 6: Object Identifier */ #define TAG_TYPE_VALUE_SEQUENCE 0x30 /* 16: Sequence/sequence of */ #define TAG_TYPE_VALUE_SET 0x31 /* 17: Set/set of */ #define TAG_TYPE_VALUE_UTF8STRING 0x0C /* 12: UTF8 string */ #define TAG_TYPE_VALUE_PRINTABLESTRING 0x13 /* 19: Printable string (ASCII subset) */ #define LEN_XTND 0x80 /* Indefinite or long form */ #define LEN_MASK 0x7F /* Bits 7 - 1 */ STATIC UINT8 mSubjectCommonNameOID[] = {0x55, 0x04, 0x03}; /* 2.5.4.3 */ typedef struct { EFI_GUID *SignatureType; EFI_STRING_ID StringId; } SECURE_BOOT_SIGNATURE_TYPE_HII_INFO; STATIC SECURE_BOOT_SIGNATURE_TYPE_HII_INFO mSigTypeHiiInfo[] = { {&gEfiCertRsa2048Guid , STRING_TOKEN (STR_SIGNATURE_TYPE_RSA2048_SHA256)}, {&gEfiCertX509Guid , STRING_TOKEN (STR_SIGNATURE_TYPE_PCKS7) }, {&gEfiCertSha1Guid , STRING_TOKEN (STR_SIGNATURE_TYPE_SHA1) }, {&gEfiCertSha256Guid , STRING_TOKEN (STR_SIGNATURE_TYPE_SHA256) }, {&gEfiCertSha512Guid , STRING_TOKEN (STR_SIGNATURE_TYPE_SHA512) }, {&gEfiCertX509Sha256Guid, STRING_TOKEN (STR_SIGNATURE_TYPE_X509_SHA256) }, {&gEfiCertX509Sha384Guid, STRING_TOKEN (STR_SIGNATURE_TYPE_X509_SHA384) }, {&gEfiCertX509Sha512Guid, STRING_TOKEN (STR_SIGNATURE_TYPE_X509_SHA512) } }; typedef struct { UINT8 *VarData; UINTN VarDataSize; } SECURE_BOOT_VAR_INFO; STATIC SECURE_BOOT_VAR_INFO mPkVarInfo = {NULL, 0}; STATIC SECURE_BOOT_VAR_INFO mKekVarInfo = {NULL, 0}; STATIC SECURE_BOOT_VAR_INFO mDbVarInfo = {NULL, 0}; STATIC SECURE_BOOT_VAR_INFO mDbxVarInfo = {NULL, 0}; STATIC SECURE_BOOT_VAR_INFO mDbtVarInfo = {NULL, 0}; STATIC SECURE_BOOT_VAR_INFO mDbrVarInfo = {NULL, 0}; STRING_DEPOSITORY *mSecureBootSigOptionStrDepository; STATIC EFI_GUID mUefiCaCertificateOwnerGuid = { 0x77fa9abd, 0x0359, 0x4d32, 0xbd, 0x60, 0x28, 0xf4, 0xe7, 0x8f, 0x78, 0x4b }; STATIC UINT8 mUefiCaCertificate[] = { 0x30, 0x82, 0x06, 0x10, 0x30, 0x82, 0x03, 0xF8, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0x61, 0x08, 0xD3, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x3B, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x54, 0x68, 0x69, 0x72, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74, 0x79, 0x20, 0x4D, 0x61, 0x72, 0x6B, 0x65, 0x74, 0x70, 0x6C, 0x61, 0x63, 0x65, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x31, 0x30, 0x36, 0x32, 0x37, 0x32, 0x31, 0x32, 0x32, 0x34, 0x35, 0x5A, 0x17, 0x0D, 0x32, 0x36, 0x30, 0x36, 0x32, 0x37, 0x32, 0x31, 0x33, 0x32, 0x34, 0x35, 0x5A, 0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x55, 0x45, 0x46, 0x49, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xA5, 0x08, 0x6C, 0x4C, 0xC7, 0x45, 0x09, 0x6A, 0x4B, 0x0C, 0xA4, 0xC0, 0x87, 0x7F, 0x06, 0x75, 0x0C, 0x43, 0x01, 0x54, 0x64, 0xE0, 0x16, 0x7F, 0x07, 0xED, 0x92, 0x7D, 0x0B, 0xB2, 0x73, 0xBF, 0x0C, 0x0A, 0xC6, 0x4A, 0x45, 0x61, 0xA0, 0xC5, 0x16, 0x2D, 0x96, 0xD3, 0xF5, 0x2B, 0xA0, 0xFB, 0x4D, 0x49, 0x9B, 0x41, 0x80, 0x90, 0x3C, 0xB9, 0x54, 0xFD, 0xE6, 0xBC, 0xD1, 0x9D, 0xC4, 0xA4, 0x18, 0x8A, 0x7F, 0x41, 0x8A, 0x5C, 0x59, 0x83, 0x68, 0x32, 0xBB, 0x8C, 0x47, 0xC9, 0xEE, 0x71, 0xBC, 0x21, 0x4F, 0x9A, 0x8A, 0x7C, 0xFF, 0x44, 0x3F, 0x8D, 0x8F, 0x32, 0xB2, 0x26, 0x48, 0xAE, 0x75, 0xB5, 0xEE, 0xC9, 0x4C, 0x1E, 0x4A, 0x19, 0x7E, 0xE4, 0x82, 0x9A, 0x1D, 0x78, 0x77, 0x4D, 0x0C, 0xB0, 0xBD, 0xF6, 0x0F, 0xD3, 0x16, 0xD3, 0xBC, 0xFA, 0x2B, 0xA5, 0x51, 0x38, 0x5D, 0xF5, 0xFB, 0xBA, 0xDB, 0x78, 0x02, 0xDB, 0xFF, 0xEC, 0x0A, 0x1B, 0x96, 0xD5, 0x83, 0xB8, 0x19, 0x13, 0xE9, 0xB6, 0xC0, 0x7B, 0x40, 0x7B, 0xE1, 0x1F, 0x28, 0x27, 0xC9, 0xFA, 0xEF, 0x56, 0x5E, 0x1C, 0xE6, 0x7E, 0x94, 0x7E, 0xC0, 0xF0, 0x44, 0xB2, 0x79, 0x39, 0xE5, 0xDA, 0xB2, 0x62, 0x8B, 0x4D, 0xBF, 0x38, 0x70, 0xE2, 0x68, 0x24, 0x14, 0xC9, 0x33, 0xA4, 0x08, 0x37, 0xD5, 0x58, 0x69, 0x5E, 0xD3, 0x7C, 0xED, 0xC1, 0x04, 0x53, 0x08, 0xE7, 0x4E, 0xB0, 0x2A, 0x87, 0x63, 0x08, 0x61, 0x6F, 0x63, 0x15, 0x59, 0xEA, 0xB2, 0x2B, 0x79, 0xD7, 0x0C, 0x61, 0x67, 0x8A, 0x5B, 0xFD, 0x5E, 0xAD, 0x87, 0x7F, 0xBA, 0x86, 0x67, 0x4F, 0x71, 0x58, 0x12, 0x22, 0x04, 0x22, 0x22, 0xCE, 0x8B, 0xEF, 0x54, 0x71, 0x00, 0xCE, 0x50, 0x35, 0x58, 0x76, 0x95, 0x08, 0xEE, 0x6A, 0xB1, 0xA2, 0x01, 0xD5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x76, 0x30, 0x82, 0x01, 0x72, 0x30, 0x12, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x23, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x02, 0x04, 0x16, 0x04, 0x14, 0xF8, 0xC1, 0x6B, 0xB7, 0x7F, 0x77, 0x53, 0x4A, 0xF3, 0x25, 0x37, 0x1D, 0x4E, 0xA1, 0x26, 0x7B, 0x0F, 0x20, 0x70, 0x80, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x13, 0xAD, 0xBF, 0x43, 0x09, 0xBD, 0x82, 0x70, 0x9C, 0x8C, 0xD5, 0x4F, 0x31, 0x6E, 0xD5, 0x22, 0x98, 0x8A, 0x1B, 0xD4, 0x30, 0x19, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x04, 0x0C, 0x1E, 0x0A, 0x00, 0x53, 0x00, 0x75, 0x00, 0x62, 0x00, 0x43, 0x00, 0x41, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x45, 0x66, 0x52, 0x43, 0xE1, 0x7E, 0x58, 0x11, 0xBF, 0xD6, 0x4E, 0x9E, 0x23, 0x55, 0x08, 0x3B, 0x3A, 0x22, 0x6A, 0xA8, 0x30, 0x5C, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x55, 0x30, 0x53, 0x30, 0x51, 0xA0, 0x4F, 0xA0, 0x4D, 0x86, 0x4B, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x43, 0x6F, 0x72, 0x54, 0x68, 0x69, 0x50, 0x61, 0x72, 0x4D, 0x61, 0x72, 0x52, 0x6F, 0x6F, 0x5F, 0x32, 0x30, 0x31, 0x30, 0x2D, 0x31, 0x30, 0x2D, 0x30, 0x35, 0x2E, 0x63, 0x72, 0x6C, 0x30, 0x60, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x54, 0x30, 0x52, 0x30, 0x50, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x44, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x43, 0x6F, 0x72, 0x54, 0x68, 0x69, 0x50, 0x61, 0x72, 0x4D, 0x61, 0x72, 0x52, 0x6F, 0x6F, 0x5F, 0x32, 0x30, 0x31, 0x30, 0x2D, 0x31, 0x30, 0x2D, 0x30, 0x35, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x35, 0x08, 0x42, 0xFF, 0x30, 0xCC, 0xCE, 0xF7, 0x76, 0x0C, 0xAD, 0x10, 0x68, 0x58, 0x35, 0x29, 0x46, 0x32, 0x76, 0x27, 0x7C, 0xEF, 0x12, 0x41, 0x27, 0x42, 0x1B, 0x4A, 0xAA, 0x6D, 0x81, 0x38, 0x48, 0x59, 0x13, 0x55, 0xF3, 0xE9, 0x58, 0x34, 0xA6, 0x16, 0x0B, 0x82, 0xAA, 0x5D, 0xAD, 0x82, 0xDA, 0x80, 0x83, 0x41, 0x06, 0x8F, 0xB4, 0x1D, 0xF2, 0x03, 0xB9, 0xF3, 0x1A, 0x5D, 0x1B, 0xF1, 0x50, 0x90, 0xF9, 0xB3, 0x55, 0x84, 0x42, 0x28, 0x1C, 0x20, 0xBD, 0xB2, 0xAE, 0x51, 0x14, 0xC5, 0xC0, 0xAC, 0x97, 0x95, 0x21, 0x1C, 0x90, 0xDB, 0x0F, 0xFC, 0x77, 0x9E, 0x95, 0x73, 0x91, 0x88, 0xCA, 0xBD, 0xBD, 0x52, 0xB9, 0x05, 0x50, 0x0D, 0xDF, 0x57, 0x9E, 0xA0, 0x61, 0xED, 0x0D, 0xE5, 0x6D, 0x25, 0xD9, 0x40, 0x0F, 0x17, 0x40, 0xC8, 0xCE, 0xA3, 0x4A, 0xC2, 0x4D, 0xAF, 0x9A, 0x12, 0x1D, 0x08, 0x54, 0x8F, 0xBD, 0xC7, 0xBC, 0xB9, 0x2B, 0x3D, 0x49, 0x2B, 0x1F, 0x32, 0xFC, 0x6A, 0x21, 0x69, 0x4F, 0x9B, 0xC8, 0x7E, 0x42, 0x34, 0xFC, 0x36, 0x06, 0x17, 0x8B, 0x8F, 0x20, 0x40, 0xC0, 0xB3, 0x9A, 0x25, 0x75, 0x27, 0xCD, 0xC9, 0x03, 0xA3, 0xF6, 0x5D, 0xD1, 0xE7, 0x36, 0x54, 0x7A, 0xB9, 0x50, 0xB5, 0xD3, 0x12, 0xD1, 0x07, 0xBF, 0xBB, 0x74, 0xDF, 0xDC, 0x1E, 0x8F, 0x80, 0xD5, 0xED, 0x18, 0xF4, 0x2F, 0x14, 0x16, 0x6B, 0x2F, 0xDE, 0x66, 0x8C, 0xB0, 0x23, 0xE5, 0xC7, 0x84, 0xD8, 0xED, 0xEA, 0xC1, 0x33, 0x82, 0xAD, 0x56, 0x4B, 0x18, 0x2D, 0xF1, 0x68, 0x95, 0x07, 0xCD, 0xCF, 0xF0, 0x72, 0xF0, 0xAE, 0xBB, 0xDD, 0x86, 0x85, 0x98, 0x2C, 0x21, 0x4C, 0x33, 0x2B, 0xF0, 0x0F, 0x4A, 0xF0, 0x68, 0x87, 0xB5, 0x92, 0x55, 0x32, 0x75, 0xA1, 0x6A, 0x82, 0x6A, 0x3C, 0xA3, 0x25, 0x11, 0xA4, 0xED, 0xAD, 0xD7, 0x04, 0xAE, 0xCB, 0xD8, 0x40, 0x59, 0xA0, 0x84, 0xD1, 0x95, 0x4C, 0x62, 0x91, 0x22, 0x1A, 0x74, 0x1D, 0x8C, 0x3D, 0x47, 0x0E, 0x44, 0xA6, 0xE4, 0xB0, 0x9B, 0x34, 0x35, 0xB1, 0xFA, 0xB6, 0x53, 0xA8, 0x2C, 0x81, 0xEC, 0xA4, 0x05, 0x71, 0xC8, 0x9D, 0xB8, 0xBA, 0xE8, 0x1B, 0x44, 0x66, 0xE4, 0x47, 0x54, 0x0E, 0x8E, 0x56, 0x7F, 0xB3, 0x9F, 0x16, 0x98, 0xB2, 0x86, 0xD0, 0x68, 0x3E, 0x90, 0x23, 0xB5, 0x2F, 0x5E, 0x8F, 0x50, 0x85, 0x8D, 0xC6, 0x8D, 0x82, 0x5F, 0x41, 0xA1, 0xF4, 0x2E, 0x0D, 0xE0, 0x99, 0xD2, 0x6C, 0x75, 0xE4, 0xB6, 0x69, 0xB5, 0x21, 0x86, 0xFA, 0x07, 0xD1, 0xF6, 0xE2, 0x4D, 0xD1, 0xDA, 0xAD, 0x2C, 0x77, 0x53, 0x1E, 0x25, 0x32, 0x37, 0xC7, 0x6C, 0x52, 0x72, 0x95, 0x86, 0xB0, 0xF1, 0x35, 0x61, 0x6A, 0x19, 0xF5, 0xB2, 0x3B, 0x81, 0x50, 0x56, 0xA6, 0x32, 0x2D, 0xFE, 0xA2, 0x89, 0xF9, 0x42, 0x86, 0x27, 0x18, 0x55, 0xA1, 0x82, 0xCA, 0x5A, 0x9B, 0xF8, 0x30, 0x98, 0x54, 0x14, 0xA6, 0x47, 0x96, 0x25, 0x2F, 0xC8, 0x26, 0xE4, 0x41, 0x94, 0x1A, 0x5C, 0x02, 0x3F, 0xE5, 0x96, 0xE3, 0x85, 0x5B, 0x3C, 0x3E, 0x3F, 0xBB, 0x47, 0x16, 0x72, 0x55, 0xE2, 0x25, 0x22, 0xB1, 0xD9, 0x7B, 0xE7, 0x03, 0x06, 0x2A, 0xA3, 0xF7, 0x1E, 0x90, 0x46, 0xC3, 0x00, 0x0D, 0xD6, 0x19, 0x89, 0xE3, 0x0E, 0x35, 0x27, 0x62, 0x03, 0x71, 0x15, 0xA6, 0xEF, 0xD0, 0x27, 0xA0, 0xA0, 0x59, 0x37, 0x60, 0xF8, 0x38, 0x94, 0xB8, 0xE0, 0x78, 0x70, 0xF8, 0xBA, 0x4C, 0x86, 0x87, 0x94, 0xF6, 0xE0, 0xAE, 0x02, 0x45, 0xEE, 0x65, 0xC2, 0xB6, 0xA3, 0x7E, 0x69, 0x16, 0x75, 0x07, 0x92, 0x9B, 0xF5, 0xA6, 0xBC, 0x59, 0x83, 0x58 }; /** Worker function that prints an binary data into specified string buffer. @param[in] BinaryBuffer Pointer to binary buffer @param[in] BinaryBufferSize Size in bytes of binary buffer @param[out] StrBuffer Pointer to output string buffer @param[in] StrBufferSize Size in bytes of output string buffer @retval EFI_SUCCESS The binary data was successfully converted to the string buffer. @retval EFI_INVALID_PARAMETER StrBuffer is NULL or StrBufferSize is zero. **/ STATIC EFI_STATUS BinaryToString ( IN UINT8 *BinaryBuffer, IN UINTN BinaryBufferSize, IN CHAR16 *StrBuffer, IN UINTN StrBufferSize ) { UINTN Index; UINTN Count; UINTN LenPerChar; if (StrBuffer == NULL || StrBufferSize == 0) { return EFI_INVALID_PARAMETER; } ZeroMem (StrBuffer, StrBufferSize); if (BinaryBuffer == NULL || BinaryBufferSize == 0) { return EFI_SUCCESS; } LenPerChar = 3; Count = MIN(StrBufferSize / sizeof (CHAR16) / LenPerChar, BinaryBufferSize); for (Index = 0; Index < Count; Index++) { UnicodeSPrint (&StrBuffer[Index * LenPerChar], LenPerChar * sizeof (CHAR16), L"%02x", BinaryBuffer[Index]); StrBuffer[(Index + 1) * LenPerChar - 1] = ' '; } if (Index > 1 && BinaryBufferSize > Count) { StrBuffer[Index * LenPerChar - 2] = '.'; StrBuffer[Index * LenPerChar - 3] = '.'; StrBuffer[Index * LenPerChar - 4] = '.'; } if (Index > 0) { StrBuffer[Index * LenPerChar - 1] = CHAR_NULL; } return EFI_SUCCESS; } /** Get the string of signature type GUID. @param[in] HiiHandle HII handle @param[in] SignatureType Pointer to signature type GUID @return The pointer of signature type string or NULL if fail to get string. **/ STATIC CHAR16 * GetSigTypeStr ( IN EFI_HII_HANDLE HiiHandle, IN EFI_GUID *SignatureType ) { UINTN Index; for (Index = 0; Index < sizeof (mSigTypeHiiInfo) / sizeof (SECURE_BOOT_SIGNATURE_TYPE_HII_INFO); Index++) { if (CompareGuid (SignatureType, mSigTypeHiiInfo[Index].SignatureType)) { return HiiGetString (HiiHandle, mSigTypeHiiInfo[Index].StringId, NULL); } } return HiiGetString (HiiHandle, STRING_TOKEN (STR_SIGNATURE_TYPE_UNKNOWN), NULL); } /** Get DER Encoded header info by ASN.1 TLV(Type-Length-Value) encoding from DER Encoded buffer. @param[in] DerData Pointer to DER buffer @param[in] DerDataSize Size in bytes of DER buffer @param[out] EncodedHeaderSize Return the size of DER Encoded header @param[out] EncodedTag Return the tag value of DER @param[out] EncodedValueSize Return the size of DER Encoded value @retval EFI_SUCCESS Get DER Encoded header info successfully. @retval EFI_INVALID_PARAMETER Input parameter is invalid. @retval EFI_NOT_FOUND DER Encoded header is incorrect. **/ STATIC EFI_STATUS GetDerEncodedHeaderInfo ( IN UINT8 *DerData, IN UINTN DerDataSize, OUT UINTN *EncodedHeaderSize, OUT UINT8 *EncodedTag, OUT UINT32 *EncodedValueSize ) { UINTN Offset; UINT8 Tag; UINT32 Size; UINT32 Length; UINT32 Index; if (DerData == NULL || DerDataSize == 0 || EncodedHeaderSize == NULL || EncodedTag == NULL || EncodedValueSize == NULL) { return EFI_INVALID_PARAMETER; } Offset = 0; Tag = DerData[Offset++]; Length = DerData[Offset++]; if ((Length & LEN_XTND) != 0) { Length &= LEN_MASK; if (Length > 4) { return EFI_NOT_FOUND; } Size = 0; for (Index = 0; Index < Length; Index++) { Size = (Size << 8) | DerData[Offset++]; } } else { Size = Length; } *EncodedHeaderSize = Offset; *EncodedTag = Tag; *EncodedValueSize = Size; return EFI_SUCCESS; } /** Convert UTF8 string to UNICODE string. UTF8 Encoding Table Bits per Character | Unicode Character Range | Unicode Binary Encoding | UTF8 Binary Encoding 0-7 | 0x0000 - 0x007F | 00000000 0xxxxxxx | 0xxxxxxx 8-11 | 0x0080 - 0x07FF | 00000xxx xxxxxxxx | 110xxxxx 10xxxxxx 12-16 | 0x0800 - 0xFFFF | xxxxxxxx xxxxxxxx | 1110xxxx 10xxxxxx 10xxxxxx @param[in] Utf8Str Pointer to UTF8 string. @param[in] Utf8StrSize Size of UTF8 string in bytes. @param[out] StrBuffer Pointer to output string buffer @param[in] StrBufferSize Size in bytes of output string buffer **/ STATIC VOID Utf8StrToUnicodeStr ( IN UINT8 *Utf8Str, IN UINTN Utf8StrSize, OUT CHAR16 *StrBuffer, IN UINTN StrBufferSize ) { UINTN Index; UINTN Utf8Index; UINT8 UnicodeByte0; UINT8 UnicodeByte1; UINT8 Byte0; UINT8 Byte1; UINT8 Byte2; UINTN Count; if (Utf8Str == NULL || StrBuffer == NULL) { return; } Count = (StrBufferSize / sizeof (CHAR16) - 1); Utf8Index = 0; for (Index = 0; Index < Count; Index++) { if ((Utf8Str[Index] & 0x80) == 0) { if (Utf8Index + 1 > Utf8StrSize) { break; } StrBuffer[Index] = Utf8Str[Utf8Index]; Utf8Index++; } else if ((Utf8Str[Index] & 0xE0) == 0xC0) { if (Utf8Index + 2 > Utf8StrSize) { break; } Byte0 = Utf8Str[Utf8Index + 1]; Byte1 = Utf8Str[Utf8Index]; UnicodeByte0 = (UINT8) ((Byte1 << 6) | (Byte0 & 0x3f)); UnicodeByte1 = (UINT8) ((Byte1 >> 2) & 0x07); StrBuffer[Index] = (CHAR16) (UnicodeByte0 | (UnicodeByte1 << 8)); Utf8Index += 2; } else if ((Utf8Str[Index] & 0xF0) == 0xE0) { if (Utf8Index + 3 > Utf8StrSize) { break; } Byte0 = Utf8Str[Utf8Index + 2]; Byte1 = Utf8Str[Utf8Index + 1]; Byte2 = Utf8Str[Utf8Index]; UnicodeByte0 = (UINT8) ((Byte1 << 6) | (Byte0 & 0x3f)); UnicodeByte1 = (UINT8) ((Byte2 << 4) | ((Byte1 >> 2) & 0x0f)); StrBuffer[Index] = (CHAR16) (UnicodeByte0 | (UnicodeByte1 << 8)); Utf8Index += 3; } else { break; } } StrBuffer[Index] = CHAR_NULL; } /** Get CN(Common Name) from subject buffer. @param[in] Subject Pointer to subject buffer @param[in] SubjectSize Size in bytes of subject buffer @param[out] StrBuffer Pointer to output string buffer @param[in] StrBufferSize Size in bytes of output string buffer @retval EFI_SUCCESS Get CN successfully. @retval EFI_INVALID_PARAMETER Subject is NULL or SubjectSize is zero. @retval EFI_NOT_FOUND CN is not found. @retval EFI_ABORTED DER Encoded header is invalid. **/ STATIC EFI_STATUS GetSubjectCommonName ( IN UINT8 *Subject, IN UINTN SubjectSize, OUT CHAR16 *StrBuffer, IN UINTN StrBufferSize ) { EFI_STATUS Status; UINTN HeaderSize; UINT8 Tag; UINT32 ValueSize; UINT8 *DataPtr; UINTN DataSize; UINT8 *ChildData; UINTN ChildDataSize; UINT8 *GrandChildData; UINTN GrandChilddDataSize; UINT8 *Oid; UINT32 OidSize; CHAR8 *AsciiStr; UINTN Index; UINTN Count; if (Subject == NULL || SubjectSize == 0) { return EFI_INVALID_PARAMETER; } // // Parsing method is referenced from CERT_getSubjectCommonNameAux() in BaseCryptLib. // // now get the child with the COMMON NAME OID 2.5.4.3 */ // Name ::= SEQUENCE of RelativeDistinguishedName // RelativeDistinguishedName = SET of AttributeValueAssertion // AttributeValueAssertion = SEQUENCE { attributeType OID; attributeValue ANY } // /* Name is a sequence */ Status = GetDerEncodedHeaderInfo (Subject, SubjectSize, &HeaderSize, &Tag, &ValueSize); if (EFI_ERROR (Status) || Tag != TAG_TYPE_VALUE_SEQUENCE) { return EFI_ABORTED; } DataPtr = Subject + HeaderSize; DataSize = ValueSize; while (DataSize > 0) { /* child should be a SET */ Status = GetDerEncodedHeaderInfo (DataPtr, DataSize, &HeaderSize, &Tag, &ValueSize); if (EFI_ERROR (Status) || Tag != TAG_TYPE_VALUE_SET) { return EFI_ABORTED; } ChildData = DataPtr + HeaderSize; ChildDataSize = ValueSize; DataPtr = DataPtr + (HeaderSize + ChildDataSize); DataSize = DataSize - (HeaderSize + ValueSize); /* GrandChild should be a SEQUENCE */ Status = GetDerEncodedHeaderInfo (ChildData, ChildDataSize, &HeaderSize, &Tag, &ValueSize); if (EFI_ERROR (Status) || Tag != TAG_TYPE_VALUE_SEQUENCE) { return EFI_ABORTED; } GrandChildData = ChildData + HeaderSize; GrandChilddDataSize = ValueSize; Status = GetDerEncodedHeaderInfo (GrandChildData, GrandChilddDataSize, &HeaderSize, &Tag, &ValueSize); if (EFI_ERROR (Status) || Tag != TAG_TYPE_VALUE_OID) { return EFI_ABORTED; } Oid = GrandChildData + HeaderSize; OidSize = ValueSize; if (OidSize != sizeof (mSubjectCommonNameOID) || CompareMem (Oid, mSubjectCommonNameOID, OidSize) != 0) { continue; } GrandChildData += (HeaderSize + ValueSize); GrandChilddDataSize -= (HeaderSize + ValueSize); Status = GetDerEncodedHeaderInfo (GrandChildData, GrandChilddDataSize, &HeaderSize, &Tag, &ValueSize); if (EFI_ERROR (Status) || (Tag != TAG_TYPE_VALUE_PRINTABLESTRING && Tag != TAG_TYPE_VALUE_UTF8STRING)) { return EFI_ABORTED; } if (Tag == TAG_TYPE_VALUE_UTF8STRING) { Utf8StrToUnicodeStr (GrandChildData + HeaderSize, ValueSize, StrBuffer, StrBufferSize); } else { AsciiStr = (CHAR8 *) (GrandChildData + HeaderSize); Count = MIN (ValueSize, (StrBufferSize / sizeof (CHAR16) - 1)); for (Index = 0; Index < Count; Index++) { StrBuffer[Index] = (CHAR16) AsciiStr[Index]; } StrBuffer[Index] = CHAR_NULL; } return EFI_SUCCESS; } return EFI_NOT_FOUND; } /** Get the display string of PKCS7 signature buffer. Display string is determined by subject CN(Common Name). @param[in] SignatureBuffer Pointer to PKCS7 signature buffer @param[in] SignatureBufferSize Size in bytes of PKCS7 signature buffer @param[out] StrBuffer Pointer to output string buffer @param[in] StrBufferSize Size in bytes of output string buffer @retval EFI_SUCCESS Get the display string successfully. @retval EFI_NOT_FOUND Subject CN is not found. @retval EFI_OUT_OF_RESOURCES Fail to allocate memory. @retval Other Fail to get CryptoServicesProtocol instance or get subject CN. **/ STATIC EFI_STATUS GetPkcs7DisplayStr ( IN UINT8 *SignatureBuffer, IN UINTN SignatureBufferSize, OUT CHAR16 *StrBuffer, IN UINTN StrBufferSize ) { EFI_STATUS Status; CRYPTO_SERVICES_PROTOCOL *CryptoService; UINT8 *Subject; UINTN SubjectSize; UINT16 *SubjectEx; UINTN SubjectExSize; BOOLEAN Success; Status = gBS->LocateProtocol (&gCryptoServicesProtocolGuid, NULL, (VOID **) &CryptoService); if (EFI_ERROR (Status)) { return Status; } Subject = NULL; SubjectSize = 0; Success = CryptoService->X509GetSubjectName ( SignatureBuffer, SignatureBufferSize, Subject, &SubjectSize ); if (Success || SubjectSize == 0) { Success = CryptoService->X509GetSubjectNameEx ( SignatureBuffer, SignatureBufferSize, &SubjectEx, &SubjectExSize ); if (!Success) { return EFI_NOT_FOUND; } StrBuffer[(SubjectExSize / sizeof (CHAR16)) - 1] = CHAR_NULL; CopyMem (StrBuffer, SubjectEx, MIN (StrBufferSize - sizeof (CHAR16), SubjectExSize)); FreePool (SubjectEx); return EFI_SUCCESS; } Subject = AllocatePool (SubjectSize); if (Subject == NULL) { return EFI_OUT_OF_RESOURCES; } Success = CryptoService->X509GetSubjectName ( SignatureBuffer, SignatureBufferSize, Subject, &SubjectSize ); if (!Success) { FreePool (Subject); return EFI_NOT_FOUND; } Status = GetSubjectCommonName (Subject, SubjectSize, StrBuffer, StrBufferSize); FreePool (Subject); return Status; } /** Get the display string of signature buffer. @param[in] SignatureType Pointer to signature type GUID @param[in] SignatureBuffer Pointer to signature buffer @param[in] SignatureBufferSize Size in bytes of signature buffer @param[out] StrBuffer Pointer to output string buffer @param[in] StrBufferSize Size in bytes of output string buffer @retval EFI_SUCCESS Get the display string successfully. @retval Other Fail to get PKCS7 display string or binary string. **/ STATIC EFI_STATUS GetSignatureDisplayStr ( IN EFI_GUID *SignatureType, IN UINT8 *SignatureBuffer, IN UINT32 SignatureBufferSize, OUT CHAR16 *StrBuffer, IN UINTN StrBufferSize ) { if (CompareGuid (SignatureType, &gEfiCertX509Guid)) { return GetPkcs7DisplayStr (SignatureBuffer, SignatureBufferSize, StrBuffer, StrBufferSize); } else { return BinaryToString (SignatureBuffer, SignatureBufferSize, StrBuffer, StrBufferSize); } } /** Get the pointer of secure boot variable info by input secure boot manager state. @param[in] SecureBootMgrState Secure boot manager state @return The pointer of secure boot variable info or NULL if secure boot manager state is invalid. **/ STATIC SECURE_BOOT_VAR_INFO * GetSecureBootVarInfo ( IN SECURE_BOOT_MANAGER_STATE SecureBootMgrState ) { switch (SecureBootMgrState) { case PkForm: return &mPkVarInfo; case KekForm: return &mKekVarInfo; case HashImageForm: case DbForm: return &mDbVarInfo; case DbxForm: return &mDbxVarInfo; case DbtForm: return &mDbtVarInfo; case DbrForm: return &mDbrVarInfo; default: return NULL; } } /** Check to see if input secure boot variable is modified or not by comparing secure boot variable in NV storage. @param[in] VarName Pointer to secure boot variable name @param[in] VendorGuid Pointer to secure boot variable vendor GUID @param[in] CurrVarData Pointer to secure boot variable buffer @param[in] CurrVarDataSize Size in bytes of secure boot variable buffer @retval TRUE The input secure boot variable is modified. @retval FALSE The input secure boot variable is not modified. **/ STATIC BOOLEAN IsSecureBootVarModified ( IN CHAR16 *VarName, IN EFI_GUID *VendorGuid, IN UINT8 *CurrVarData, IN UINTN CurrVarDataSize ) { EFI_STATUS Status; UINTN OrgVarDataSize; UINT8 *OrgVarData; BOOLEAN IsModified; Status = CommonGetVariableDataAndSize (VarName, VendorGuid, &OrgVarDataSize, (VOID **) &OrgVarData); if (EFI_ERROR (Status)) { OrgVarData = NULL; OrgVarDataSize = 0; } if (OrgVarDataSize != CurrVarDataSize) { IsModified = TRUE; } else if (OrgVarData != NULL && CurrVarData != NULL && CompareMem (OrgVarData, CurrVarData, CurrVarDataSize) != 0) { IsModified = TRUE; } else { IsModified = FALSE; } SecureBootSafeFreePool ((VOID **) &OrgVarData); return IsModified; } /** Check to see if input signature is existing in input signature list or not. @param[in] SigList Pointer to signature list @param[in] Sig Pointer to signature buffer @param[in] SigSize Size in bytes of signature buffer @retval TRUE The input signature is existing in input signature list. @retval FALSE The input signature is not existing in input signature list. **/ STATIC BOOLEAN IsSignatureExistence ( IN EFI_SIGNATURE_LIST *SigList, IN EFI_SIGNATURE_DATA *Sig, IN UINTN SigSize ) { UINT8 *CurrSig; UINTN SigCount; UINTN Index; if (SigList == NULL || Sig == NULL || SigSize == 0) { return FALSE; } if (SigSize != SigList->SignatureSize) { return FALSE; } CurrSig = ((UINT8 *) SigList) + sizeof (EFI_SIGNATURE_LIST) + SigList->SignatureHeaderSize; SigCount = (SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigList->SignatureHeaderSize) / SigList->SignatureSize; for (Index = 0; Index < SigCount; Index++) { if (CompareMem (CurrSig, Sig, SigSize) == 0) { return TRUE; } CurrSig += SigList->SignatureSize; } return FALSE; } /** Check to see if input signature is existing in input signature list or not. @param[in] SigList Pointer to signature list @param[in] Sig Pointer to signature buffer @param[in] SigSize Size in bytes of signature buffer @retval TRUE The input signature is existing in input signature list. @retval FALSE The input signature is not existing in input signature list. **/ STATIC BOOLEAN IsShaSignatureType ( IN EFI_GUID *SignatureType ) { if (CompareGuid (SignatureType, &gEfiCertSha1Guid ) || CompareGuid (SignatureType, &gEfiCertSha256Guid) || CompareGuid (SignatureType, &gEfiCertSha512Guid)) { return TRUE; } return FALSE; } /** Internal function to check the input signature buffer is whether a valid X509 certificate. @param[in] SignatureBuffer Pointer to PKCS7 signature buffer @param[in] SignatureBufferSize Size in bytes of PKCS7 signature buffer @retval TRUE Input buffer is a valid X509 certificate. @retval FALSE Input buffer isn't a valid X509 certificate. **/ STATIC BOOLEAN IsValidCertificate ( IN UINT8 *SignatureBuffer, IN UINTN SignatureBufferSize ) { EFI_STATUS Status; CRYPTO_SERVICES_PROTOCOL *CryptoService; UINT8 *Issuer; UINTN IssuerSize; BOOLEAN Success; Status = gBS->LocateProtocol (&gCryptoServicesProtocolGuid, NULL, (VOID **) &CryptoService); if (EFI_ERROR (Status)) { return FALSE; } Issuer = NULL; IssuerSize = 0; Success = CryptoService->X509GetIssuerName ( SignatureBuffer, SignatureBufferSize, Issuer, &IssuerSize ); if (Success || IssuerSize == 0) { return FALSE; } return TRUE; } /** Add signature to specific secure boot variable determined by input secure boot manager state. @param[in] SecureBootMgrState Secure boot manager state @param[in] SignatureType Pointer to signature type GUID @param[in] SignatureOwnerGuid Pointer to signature owner GUID @param[in] SignatureData Pointer to signature data buffer @param[in] SignatureDataSize Size in bytes of signature data buffer @param[in] UpdateForm Need update state to form or not @retval EFI_SUCCESS Add signature successfully. @retval EFI_NOT_FOUND Target secure boot variable info is not found. @retval EFI_ABORTED Reject to add signature because PK is existing. @retval EFI_ABORTED There is an identical signature in target secure boot variable. @retval EFI_OUT_OF_RESOURCES Fail to allocate memory. **/ EFI_STATUS SecureBootVarAddSignature ( IN SECURE_BOOT_MANAGER_STATE SecureBootMgrState, IN EFI_GUID *SignatureType, IN EFI_GUID *SignatureOwnerGuid, IN UINT8 *SignatureData, IN UINTN SignatureDataSize, IN BOOLEAN UpdateForm ) { SECURE_BOOT_VAR_INFO *VarInfo; EFI_SIGNATURE_DATA *Sig; UINTN SigSize; UINTN RemainedSize; EFI_SIGNATURE_LIST *TargetSigList; EFI_SIGNATURE_LIST *SigList; EFI_SIGNATURE_LIST *NewSigList; UINT8 *NewVarData; UINT8 *NewVarDataPtr; UINTN NewVarDataSize; UINTN Size; if (SignatureType == NULL || SignatureOwnerGuid == NULL || SignatureData == NULL || SignatureDataSize == 0) { return EFI_INVALID_PARAMETER; } VarInfo = GetSecureBootVarInfo (SecureBootMgrState); if (VarInfo == NULL) { return EFI_NOT_FOUND; } if (VarInfo == &mPkVarInfo && VarInfo->VarData != NULL) { SecureBootShowOkConfirmDlg (STRING_TOKEN (STR_PK_EXIST_ERROR_MESSAGE)); return EFI_ABORTED; } if (CompareGuid (SignatureType, &gEfiCertX509Guid)) { if (!IsValidCertificate (SignatureData, SignatureDataSize)) { SecureBootShowOkConfirmDlg (STRING_TOKEN(STR_FILE_FORMAT_INCORRECT_MESSAGE)); return EFI_INVALID_PARAMETER; } } // // Create signature. // SigSize = sizeof (EFI_SIGNATURE_DATA) - 1 + SignatureDataSize; Sig = AllocatePool (SigSize); if (Sig == NULL) { return EFI_OUT_OF_RESOURCES; } CopyGuid (&Sig->SignatureOwner, SignatureOwnerGuid); CopyMem (Sig->SignatureData, SignatureData, SignatureDataSize); RemainedSize = VarInfo->VarDataSize; SigList = (EFI_SIGNATURE_LIST *) VarInfo->VarData; if (SigList == NULL) { return EFI_NOT_FOUND; } TargetSigList = NULL; while ((RemainedSize > 0) && (RemainedSize >= SigList->SignatureListSize)) { if (SigList->SignatureListSize < sizeof (EFI_SIGNATURE_LIST)) { break; } if (SigList->SignatureSize == SigSize && CompareGuid (&SigList->SignatureType, SignatureType)) { if (IsSignatureExistence (SigList, Sig, SigSize)) { SecureBootShowOkConfirmDlg (STRING_TOKEN(STR_IDENTICAL_SIGNATURE_ERROR_MESSAGE)); FreePool (Sig); return EFI_ABORTED; } if (IsShaSignatureType (SignatureType)) { TargetSigList = SigList; break; } } RemainedSize -= SigList->SignatureListSize; SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize); } if (TargetSigList == NULL) { // // Target signature list doesn't exist. Append new signature list in the end of variable. // NewVarDataSize = VarInfo->VarDataSize + sizeof (EFI_SIGNATURE_LIST) + SigSize; if (NewVarDataSize > MAX_VARIABLE_SIZE) { SecureBootShowOkConfirmDlg (STRING_TOKEN (STR_FILE_SIZE_TOO_LARGE_MESSAGE)); return EFI_OUT_OF_RESOURCES; } NewVarData = AllocatePool (NewVarDataSize); if (NewVarData == NULL) { return EFI_OUT_OF_RESOURCES; } if (VarInfo->VarData != NULL) { CopyMem (NewVarData, VarInfo->VarData, VarInfo->VarDataSize); } NewSigList = (EFI_SIGNATURE_LIST *) (NewVarData + VarInfo->VarDataSize); NewSigList->SignatureListSize = (UINT32) (sizeof (EFI_SIGNATURE_LIST) + SigSize); NewSigList->SignatureHeaderSize = 0; NewSigList->SignatureSize = (UINT32) SigSize; CopyGuid ( &NewSigList->SignatureType, SignatureType ); CopyMem ( ((UINT8 *) NewSigList) + sizeof (EFI_SIGNATURE_LIST), Sig, SigSize ); } else { // // Target signature list exist. Append new signature in the end of target signature list. // NewVarDataSize = VarInfo->VarDataSize + SigSize; if (NewVarDataSize > MAX_VARIABLE_SIZE) { SecureBootShowOkConfirmDlg (STRING_TOKEN (STR_FILE_SIZE_TOO_LARGE_MESSAGE)); return EFI_OUT_OF_RESOURCES; } NewVarData = AllocatePool (NewVarDataSize); if (NewVarData == NULL) { return EFI_OUT_OF_RESOURCES; } NewVarDataPtr = NewVarData; RemainedSize = VarInfo->VarDataSize; Size = ((UINT8 *) TargetSigList) - VarInfo->VarData; CopyMem (NewVarDataPtr, VarInfo->VarData, Size); NewVarDataPtr += Size; RemainedSize -= Size; NewSigList = (EFI_SIGNATURE_LIST *) NewVarDataPtr; Size = TargetSigList->SignatureListSize; CopyMem (NewVarDataPtr, TargetSigList, Size); NewVarDataPtr += Size; RemainedSize -= Size; CopyMem (NewVarDataPtr, Sig, SigSize); NewVarDataPtr += SigSize; NewSigList->SignatureListSize += (UINT32) SigSize; CopyMem ( NewVarDataPtr, ((UINT8 *) TargetSigList) + TargetSigList->SignatureListSize, RemainedSize ); } SecureBootSafeFreePool ((VOID **) &VarInfo->VarData); VarInfo->VarData = NewVarData; VarInfo->VarDataSize = NewVarDataSize; if (UpdateForm) { SecureBootVarUpdateForm (mSecureBootPrivate.SecureBootMgrState); } FreePool (Sig); return EFI_SUCCESS; } /** Delete signature from specific secure boot variable determined by input secure boot manager state. @param[in] SecureBootMgrState Secure boot manager state @param[in] SignatureIndex The index value of signature which is wanted to be deleted @retval EFI_SUCCESS Delete signature successfully. @retval EFI_NOT_FOUND Target secure boot variable info is not found. @retval EFI_NOT_FOUND Signatue is not found because index value is larger than the signature count in secure boot variable. **/ EFI_STATUS SecureBootVarDeleteSignature ( IN SECURE_BOOT_MANAGER_STATE SecureBootMgrState, IN UINTN SignatureIndex ) { SECURE_BOOT_VAR_INFO *VarInfo; UINTN Index; UINTN CurrIndex; UINTN RemainedSize; EFI_SIGNATURE_LIST *SigList; UINT8 *Sig; UINTN SigCount; VarInfo = GetSecureBootVarInfo (SecureBootMgrState); if (VarInfo == NULL) { return EFI_NOT_FOUND; } CurrIndex = 0; RemainedSize = VarInfo->VarDataSize; SigList = (EFI_SIGNATURE_LIST *) VarInfo->VarData; while ((RemainedSize > 0) && (RemainedSize >= SigList->SignatureListSize)) { if (SigList->SignatureListSize < sizeof (EFI_SIGNATURE_LIST)) { break; } SigCount = (SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigList->SignatureHeaderSize) / SigList->SignatureSize; if (SignatureIndex >= CurrIndex && SignatureIndex < CurrIndex + SigCount) { if (SigCount <= 1) { // // There is only one signature in the signature list. Delete this signature list. // VarInfo->VarDataSize -= SigList->SignatureListSize; CopyMem ( SigList, ((UINT8 *) SigList) + SigList->SignatureListSize, RemainedSize - SigList->SignatureListSize ); } else { // // There are many signatures in the signature list. Delete this signature in the signature list. // Sig = ((UINT8 *) SigList) + sizeof (EFI_SIGNATURE_LIST) + SigList->SignatureHeaderSize; Index = SignatureIndex - CurrIndex; CopyMem ( Sig + SigList->SignatureSize * Index, Sig + SigList->SignatureSize * (Index + 1), SigList->SignatureSize * (SigCount - Index - 1) + (RemainedSize - SigList->SignatureListSize) ); SigList->SignatureListSize -= SigList->SignatureSize; VarInfo->VarDataSize -= SigList->SignatureSize; } if (VarInfo->VarDataSize == 0) { SecureBootSafeFreePool ((VOID **) &VarInfo->VarData); } SecureBootVarUpdateForm (mSecureBootPrivate.SecureBootMgrState); return EFI_SUCCESS; } CurrIndex += SigCount; RemainedSize -= SigList->SignatureListSize; SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize); } return EFI_NOT_FOUND; } /** Enumerating all signature from variable data to update signature question list in target VFR form. @param[in] VarData Pointer to secure boot variable data @param[in] VarDataSize Size in bytes of secure boot variable data @param[in] FormId Target form ID @param[in] LabelStartId Target start label ID @param[in] LabelEndId Target end label ID @param[in] IfrOpcode Target IFR opcode of signature @param[in] QuestionIdBase Question ID base value if QuestionOpcode is a question opcode. @param[in] QuestionIdLen Available question ID length if QuestionOpcode is a question opcode. @retval EFI_SUCCESS Update signature question list successfully. @retval EFI_OUT_OF_RESOURCES Fail to create opcode or allocate memory. **/ STATIC EFI_STATUS SecureBootVarUpdateQuestionList ( IN UINT8 *VarData, IN UINTN VarDataSize, IN EFI_FORM_ID FormId, IN UINT16 LabelStartId, IN UINT16 LabelEndId, IN UINT8 IfrOpcode, IN EFI_QUESTION_ID QuestionIdBase, IN EFI_QUESTION_ID QuestionIdLen ) { EFI_STATUS Status; EFI_HII_HANDLE HiiHandle; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; UINTN Index; CHAR16 *SigTypeStr; CHAR16 *SigDataStr; UINTN SigDataStrSize; CHAR16 *PromptStr; UINTN PromptStrSize; EFI_STRING_ID PromptStrId; CHAR16 *HelpStr; UINTN HelpStrSize; EFI_STRING_ID HelpStrId; CHAR16 GuidStr[37]; UINTN QuestionIdIndex; UINTN RemainedSize; EFI_SIGNATURE_LIST *SigList; UINTN SigCount; EFI_SIGNATURE_DATA *Sig; CHAR16 UnknownStr[] = L"Unknown"; HiiHandle = mSecureBootPrivate.HiiHandle; Status = EFI_SUCCESS; SigDataStr = NULL; PromptStr = NULL; HelpStr = NULL; // // Initialize the container for dynamic opcodes. // StartOpCodeHandle = HiiAllocateOpCodeHandle (); EndOpCodeHandle = HiiAllocateOpCodeHandle (); if (StartOpCodeHandle == NULL || EndOpCodeHandle == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Exit; } StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle , &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); if (StartLabel == NULL || EndLabel == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Exit; } StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; StartLabel->Number = LabelStartId; EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; EndLabel->Number = LabelEndId; if (VarData == NULL || VarDataSize == 0) { goto Exit; } SigDataStrSize = 100 * sizeof (CHAR16); SigDataStr = AllocateZeroPool (SigDataStrSize); PromptStrSize = SigDataStrSize + 100 * sizeof (CHAR16); PromptStr = AllocateZeroPool (PromptStrSize); HelpStrSize = 100 * sizeof (CHAR16); HelpStr = AllocateZeroPool (HelpStrSize); if (PromptStr == NULL || SigDataStr == NULL || HelpStr == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Exit; } QuestionIdIndex = 0; RemainedSize = VarDataSize; SigList = (EFI_SIGNATURE_LIST *) VarData; while ((RemainedSize > 0) && (RemainedSize >= SigList->SignatureListSize)) { if (SigList->SignatureListSize < sizeof (EFI_SIGNATURE_LIST)) { break; } SigTypeStr = GetSigTypeStr (HiiHandle, &SigList->SignatureType); if (SigTypeStr == NULL) { SigTypeStr = UnknownStr; } Sig = (EFI_SIGNATURE_DATA *) (((UINT8 *) SigList) + sizeof (EFI_SIGNATURE_LIST) + SigList->SignatureHeaderSize); SigCount = (SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigList->SignatureHeaderSize) / SigList->SignatureSize; for (Index = 0; Index < SigCount; Index++, QuestionIdIndex++) { Status = GetSignatureDisplayStr ( &SigList->SignatureType, Sig->SignatureData, SigList->SignatureSize - OFFSET_OF(EFI_SIGNATURE_DATA, SignatureData), SigDataStr, SigDataStrSize ); if (EFI_ERROR (Status)) { ZeroMem (SigDataStr, SigDataStrSize); } UnicodeSPrint (PromptStr, PromptStrSize, L"%02d. [%s] %s", QuestionIdIndex + 1, SigTypeStr, SigDataStr); PromptStrId = SecureBootGetStrTokenFromDepository (&mSecureBootPrivate, mSecureBootSigOptionStrDepository); PromptStrId = HiiSetString (HiiHandle, PromptStrId, PromptStr, NULL); SecureBootGuidToStr (&Sig->SignatureOwner, GuidStr, sizeof(GuidStr)); UnicodeSPrint (HelpStr, HelpStrSize, L"Owner_GUID: %s", GuidStr); HelpStrId = SecureBootGetStrTokenFromDepository (&mSecureBootPrivate, mSecureBootSigOptionStrDepository); HelpStrId = HiiSetString (HiiHandle, HelpStrId, HelpStr, NULL); switch (IfrOpcode) { case EFI_IFR_TEXT_OP: HiiCreateTextOpCode ( StartOpCodeHandle, PromptStrId, HelpStrId, 0 ); break; case EFI_IFR_ACTION_OP: if (QuestionIdIndex >= QuestionIdLen) { break; } HiiCreateActionOpCode ( StartOpCodeHandle, (EFI_QUESTION_ID) (QuestionIdBase + QuestionIdIndex), PromptStrId, HelpStrId, EFI_IFR_FLAG_CALLBACK, 0 ); break; } Sig = (EFI_SIGNATURE_DATA *) (((UINT8 *) Sig) + SigList->SignatureSize); } if (SigTypeStr != UnknownStr) { FreePool (SigTypeStr); } RemainedSize -= SigList->SignatureListSize; SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize); } Exit: if (StartOpCodeHandle != NULL && EndOpCodeHandle != NULL) { HiiUpdateForm ( HiiHandle, &mSecureBootGuid, FormId, StartOpCodeHandle, EndOpCodeHandle ); } if (StartOpCodeHandle != NULL) { HiiFreeOpCodeHandle (StartOpCodeHandle); } if (EndOpCodeHandle != NULL) { HiiFreeOpCodeHandle (EndOpCodeHandle); } SecureBootSafeFreePool ((VOID **) &SigDataStr); SecureBootSafeFreePool ((VOID **) &PromptStr); SecureBootSafeFreePool ((VOID **) &HelpStr); return Status; } /** Update the related forms of specified secure boot variable. @param[in] SecureBootMgrState Secure boot manager state @retval EFI_SUCCESS Update the related forms successfully. @retval EFI_NOT_FOUND Fail to get secure boot vairable info or state is unsupported. **/ EFI_STATUS SecureBootVarUpdateForm ( IN SECURE_BOOT_MANAGER_STATE SecureBootMgrState ) { SECURE_BOOT_VAR_INFO *VarInfo; EFI_FORM_ID SigListFormId; EFI_FORM_ID DeleteSigFormId; VarInfo = GetSecureBootVarInfo (SecureBootMgrState); if (VarInfo == NULL) { return EFI_NOT_FOUND; } switch (SecureBootMgrState) { case PkForm: SigListFormId = FORM_ID_PK; DeleteSigFormId = FORM_ID_PK_DELETE_SIGNATURE; break; case KekForm: SigListFormId = FORM_ID_KEK; DeleteSigFormId = FORM_ID_KEK_DELETE_SIGNATURE; break; case DbForm: SigListFormId = FORM_ID_DB; DeleteSigFormId = FORM_ID_DB_DELETE_SIGNATURE; break; case DbxForm: SigListFormId = FORM_ID_DBX; DeleteSigFormId = FORM_ID_DBX_DELETE_SIGNATURE; break; case DbtForm: SigListFormId = FORM_ID_DBT; DeleteSigFormId = FORM_ID_DBT_DELETE_SIGNATURE; break; case DbrForm: SigListFormId = FORM_ID_DBR; DeleteSigFormId = FORM_ID_DBR_DELETE_SIGNATURE; break; default: return EFI_NOT_FOUND; } SecureBootReclaimStrDepository (mSecureBootSigOptionStrDepository); if (SigListFormId != 0) { SecureBootVarUpdateQuestionList ( VarInfo->VarData, VarInfo->VarDataSize, SigListFormId, LABEL_ID_SIGNATURE_LIST_START, LABEL_ID_SIGNATURE_LIST_END, EFI_IFR_TEXT_OP, 0, 0 ); } if (DeleteSigFormId != 0) { SecureBootVarUpdateQuestionList ( VarInfo->VarData, VarInfo->VarDataSize, DeleteSigFormId, LABEL_ID_DELETE_SIGNATURE_LIST_START, LABEL_ID_DELETE_SIGNATURE_LIST_END, EFI_IFR_ACTION_OP, KEY_DELETE_SIGNATURE_QUESTION_BASE, KEY_DELETE_SIGNATURE_QUESTION_LENGTH ); } return EFI_SUCCESS; } /** Update each secure boot variable if it is modified. @retval EFI_SUCCESS Update secure boot variables successfully. **/ EFI_STATUS SecureBootVarSaveChange ( VOID ) { if (IsSecureBootVarModified (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, mPkVarInfo.VarData, mPkVarInfo.VarDataSize)) { UpdatePkVariable (mPkVarInfo.VarData, mPkVarInfo.VarDataSize); } if (IsSecureBootVarModified (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, mKekVarInfo.VarData, mKekVarInfo.VarDataSize)) { UpdateKekVariable (mKekVarInfo.VarData, mKekVarInfo.VarDataSize, UPDATE_AUTHENTICATED_VARIABLE); } if (IsSecureBootVarModified (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, mDbVarInfo.VarData, mDbVarInfo.VarDataSize)) { UpdateDbVariable (mDbVarInfo.VarData, mDbVarInfo.VarDataSize, UPDATE_AUTHENTICATED_VARIABLE); } if (IsSecureBootVarModified (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, mDbxVarInfo.VarData, mDbxVarInfo.VarDataSize)) { UpdateDbxVariable (mDbxVarInfo.VarData, mDbxVarInfo.VarDataSize, UPDATE_AUTHENTICATED_VARIABLE); } if (IsSecureBootVarModified (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, mDbtVarInfo.VarData, mDbtVarInfo.VarDataSize)) { UpdateDbtVariable (mDbtVarInfo.VarData, mDbtVarInfo.VarDataSize, UPDATE_AUTHENTICATED_VARIABLE); } if (IsSecureBootVarModified (EFI_IMAGE_SECURITY_DATABASE3, &gEfiImageSecurityDatabaseGuid, mDbrVarInfo.VarData, mDbrVarInfo.VarDataSize)) { UpdateDbrVariable (mDbrVarInfo.VarData, mDbrVarInfo.VarDataSize, UPDATE_AUTHENTICATED_VARIABLE); } return EFI_SUCCESS; } /** Initialize secure boot variable info. @retval EFI_SUCCESS Initialize secure boot variable info successfully. **/ EFI_STATUS SecureBootVarInit ( VOID ) { SecureBootSafeFreePool ((VOID **) &mPkVarInfo.VarData); SecureBootSafeFreePool ((VOID **) &mKekVarInfo.VarData); SecureBootSafeFreePool ((VOID **) &mDbVarInfo.VarData); SecureBootSafeFreePool ((VOID **) &mDbxVarInfo.VarData); SecureBootSafeFreePool ((VOID **) &mDbtVarInfo.VarData); SecureBootSafeFreePool ((VOID **) &mDbrVarInfo.VarData); mPkVarInfo.VarDataSize = 0; mKekVarInfo.VarDataSize = 0; mDbVarInfo.VarDataSize = 0; mDbxVarInfo.VarDataSize = 0; mDbtVarInfo.VarDataSize = 0; mDbrVarInfo.VarDataSize = 0; CommonGetVariableDataAndSize (EFI_PLATFORM_KEY_NAME , &gEfiGlobalVariableGuid , &mPkVarInfo.VarDataSize , (VOID **) &mPkVarInfo.VarData ); CommonGetVariableDataAndSize (EFI_KEY_EXCHANGE_KEY_NAME , &gEfiGlobalVariableGuid , &mKekVarInfo.VarDataSize, (VOID **) &mKekVarInfo.VarData); CommonGetVariableDataAndSize (EFI_IMAGE_SECURITY_DATABASE , &gEfiImageSecurityDatabaseGuid, &mDbVarInfo.VarDataSize , (VOID **) &mDbVarInfo.VarData ); CommonGetVariableDataAndSize (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, &mDbxVarInfo.VarDataSize, (VOID **) &mDbxVarInfo.VarData); CommonGetVariableDataAndSize (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, &mDbtVarInfo.VarDataSize, (VOID **) &mDbtVarInfo.VarData); CommonGetVariableDataAndSize (EFI_IMAGE_SECURITY_DATABASE3, &gEfiImageSecurityDatabaseGuid, &mDbrVarInfo.VarDataSize, (VOID **) &mDbrVarInfo.VarData); return EFI_SUCCESS; } /** Helper function to check if UEFI CA certificate is wheterh in DB. @retval TRUE There is UEFI CA certificate in DB @retval FALSE There is not UEFI Ca certificate in DB **/ BOOLEAN IsUefiCaCertificateInDb ( VOID ) { EFI_SIGNATURE_LIST *CertList; EFI_SIGNATURE_DATA *Cert; UINTN CertSize; UINTN DataSize; if (mDbVarInfo.VarDataSize == 0) { return FALSE; } DataSize = mDbVarInfo.VarDataSize; CertList = (EFI_SIGNATURE_LIST *) mDbVarInfo.VarData; while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) { // // check the size of singature list size first to make sure singature data integrity // if (CertList->SignatureListSize < sizeof (EFI_SIGNATURE_LIST)) { break; } if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); CertSize = CertList->SignatureSize - sizeof(EFI_GUID); if (CertSize == sizeof (mUefiCaCertificate) && CompareMem (Cert->SignatureData, mUefiCaCertificate, CertSize) == 0) { return TRUE; } } DataSize -= CertList->SignatureListSize; CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); } return FALSE; } /** Helper function to add UEFI CA certificate to DB. **/ VOID AddUefiCaCertificateToDb ( VOID ) { SecureBootVarAddSignature ( DbForm, &gEfiCertX509Guid, &mUefiCaCertificateOwnerGuid, mUefiCaCertificate, sizeof (mUefiCaCertificate), FALSE ); }