summaryrefslogtreecommitdiffstats
path: root/src/usr/vfs
diff options
context:
space:
mode:
authorStephen Cprek <smcprek@us.ibm.com>2017-04-10 16:32:00 -0500
committerWilliam G. Hoffa <wghoffa@us.ibm.com>2017-05-01 17:53:46 -0400
commit863b78e70f9b11e9948c380e1d5cd5790d8d9962 (patch)
tree37e0685a747c34d2bc4e58018eb2ac7f1910072a /src/usr/vfs
parent142a25c1a3453d0cc5bac4a93a2765e60a281d2d (diff)
downloadtalos-hostboot-863b78e70f9b11e9948c380e1d5cd5790d8d9962.tar.gz
talos-hostboot-863b78e70f9b11e9948c380e1d5cd5790d8d9962.zip
Port P8 HBI page verification functionality
Verify HBI pages via its securely signed hash page table Change-Id: I86d29ee393c19aa0d9c5270b0b6c561a9fc4ab51 RTC: 167668 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/39071 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com> Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Diffstat (limited to 'src/usr/vfs')
-rw-r--r--src/usr/vfs/vfsrp.C220
-rw-r--r--src/usr/vfs/vfsrp.H88
2 files changed, 255 insertions, 53 deletions
diff --git a/src/usr/vfs/vfsrp.C b/src/usr/vfs/vfsrp.C
index 125197b89..6284edd5a 100644
--- a/src/usr/vfs/vfsrp.C
+++ b/src/usr/vfs/vfsrp.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* Contributors Listed Below - COPYRIGHT 2011,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -42,6 +42,10 @@
#include <util/align.H>
#include <errl/errludstring.H>
#include <errl/errlmanager.H>
+#include <secureboot/service.H>
+#include <secureboot/containerheader.H>
+#include <kernel/console.H>
+#include <config.h>
using namespace VFS;
@@ -136,54 +140,89 @@ errlHndl_t VfsRp::_init()
{
errlHndl_t err = NULL;
size_t rc = 0;
+
+ do {
+
iv_msgQ = msg_q_create();
rc = msg_q_register(iv_msgQ, VFS_ROOT_MSG_VFS);
+ assert(rc == 0,"Msg Queue Registration failed in VFS");
+
+#ifdef CONFIG_SECUREBOOT
+ err = loadSecureSection(PNOR::HB_EXT_CODE);
+ if(err)
+ {
+ break;
+ }
+#endif
// Discover PNOR virtual address of extended image
PNOR::SectionInfo_t l_pnor_info;
-
err = PNOR::getSectionInfo(PNOR::HB_EXT_CODE, l_pnor_info);
- if(!err)
+ if(err)
{
- iv_pnor_vaddr = l_pnor_info.vaddr;
+ break;
+ }
- rc = mm_alloc_block
- (iv_msgQ,
- (void *)VFS_EXTENDED_MODULE_VADDR,
- ALIGN_PAGE(l_pnor_info.size)
- );
- if(rc == 0)
- {
- // Note: permissions are set elsewhere
+ iv_pnor_vaddr = l_pnor_info.vaddr;
+ iv_hbExtSecure = l_pnor_info.secure;
+#ifdef CONFIG_SECUREBOOT
+ // Assume if HBI is signed it also has a hash page table.
+ if (iv_hbExtSecure)
+ {
+ // store the hash page table offset for reference
+ iv_hashPageTableOffset = iv_pnor_vaddr;
+
+ // Extract total protected payload size from header
+ iv_protectedPayloadSize = l_pnor_info.secureProtectedPayloadSize;
+
+ // calculate the hash page table size
+ iv_hashPageTableSize = iv_protectedPayloadSize - VFS_MODULE_TABLE_SIZE;
+ TRACFCOMP(g_trac_vfs, "VfsRp::_init HB_EXT total payload_text_size = 0x%X, hash page table size = 0x%X",
+ l_pnor_info.secureProtectedPayloadSize,
+ iv_hashPageTableSize);
+ // skip the hash page table
+ iv_pnor_vaddr += iv_hashPageTableSize;
+ }
+#endif
- // Start msg_handler task watcher
- // NOTE: This would be a weak consistancy issues if
- // task_create were not a system call.
- task_create(VfsRp::vfsWatcher, NULL);
- }
- else
- {
- /*@ errorlog tag
- * @errortype ERRL_SEV_CRITICAL_SYS_TERM
- * @moduleid VFS_MODULE_ID
- * @reasoncode VFS_ALLOC_VMEM_FAILED
- * @userdata1 returncode from mm_alloc_block()
- * @userdata2 Size of memory to allocate
- *
- * @devdesc Could not allocate virtual memory.
- *
- */
- err = new ERRORLOG::ErrlEntry
- (
- ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity
- VFS::VFS_MODULE_ID, // moduleid
- VFS::VFS_ALLOC_VMEM_FAILED, // reason Code
- rc, // user1 = rc
- l_pnor_info.size, // user2 = size
- true /*Add HB Software Callout*/
- );
- }
+ rc = mm_alloc_block
+ (iv_msgQ,
+ (void *)VFS_EXTENDED_MODULE_VADDR,
+ ALIGN_PAGE(l_pnor_info.size)
+ );
+ if(rc == 0)
+ {
+ // Note: permissions are set elsewhere
+
+ // Start msg_handler task watcher
+ // NOTE: This would be a weak consistancy issues if
+ // task_create were not a system call.
+ task_create(VfsRp::vfsWatcher, NULL);
}
+ else
+ {
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_CRITICAL_SYS_TERM
+ * @moduleid VFS_MODULE_ID
+ * @reasoncode VFS_ALLOC_VMEM_FAILED
+ * @userdata1 returncode from mm_alloc_block()
+ * @userdata2 Size of memory to allocate
+ *
+ * @devdesc Could not allocate virtual memory.
+ *
+ */
+ err = new ERRORLOG::ErrlEntry
+ (
+ ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity
+ VFS::VFS_MODULE_ID, // moduleid
+ VFS::VFS_ALLOC_VMEM_FAILED, // reason Code
+ rc, // user1 = rc
+ l_pnor_info.size, // user2 = size
+ true /*Add HB Software Callout*/
+ );
+ break;
+ }
+ } while (0);
return err;
}
@@ -308,15 +347,30 @@ void VfsRp::msgHandler()
iv_msg = msg; // save message in case task crashes
uint64_t vaddr = msg->data[0]; //page aligned
uint64_t paddr = msg->data[1]; //page aligned
-
- vaddr -= VFS_EXTENDED_MODULE_VADDR;
- memcpy((void *)paddr, (void *)(iv_pnor_vaddr+vaddr),
- PAGE_SIZE);
-
- mm_icache_invalidate((void*)paddr,PAGE_SIZE/8);
-
+ // Get relative virtual address within VFS space
+ vaddr-=VFS_EXTENDED_MODULE_VADDR;
+ do
+ {
+#ifdef CONFIG_SECUREBOOT
+ if (SECUREBOOT::enabled() && iv_hbExtSecure)
+ {
+ errlHndl_t l_errl = verify_page(vaddr);
+ // Failed to pass secureboot verification
+ if(l_errl)
+ {
+ SECUREBOOT::handleSecurebootFailure(
+ l_errl,false);
+ msg->data[1] = -EACCES;
+ break;
+ }
+ }
+#endif
+ memcpy((void *)paddr, (void *)(iv_pnor_vaddr+vaddr),
+ PAGE_SIZE);
+ mm_icache_invalidate((void*)paddr,PAGE_SIZE/8);
+ msg->data[1] = 0;
+ } while(0);
}
- msg->data[1] = 0;
msg_respond(iv_msgQ, msg);
break;
@@ -704,6 +758,76 @@ void VfsRp::get_test_modules(std::vector<const char *> & o_list) const
}
+errlHndl_t VfsRp::verify_page(uint64_t i_vaddr, uint64_t i_baseOffset,
+ uint64_t i_hashPageTableOffset) const
+{
+ errlHndl_t l_errl = nullptr;
+ uint64_t l_pnorVaddr = iv_pnor_vaddr + i_vaddr;
+
+ // Get current hash page table entry
+ TRACDCOMP(g_trac_vfs, "VfsRp::verify_page Current Page vaddr = 0x%llX, index = %d, bin file offset = 0x%llX",
+ i_vaddr,
+ getHashPageTableIndex(i_vaddr,i_baseOffset),
+ i_vaddr+PAGE_SIZE+iv_protectedPayloadSize);
+ PAGE_TABLE_ENTRY_t* l_pageTableEntry = getHashPageTableEntry(i_vaddr,
+ i_baseOffset,
+ i_hashPageTableOffset);
+
+ // Get previous hash page table entry
+ uint64_t l_prevPage = i_vaddr - PAGE_SIZE;
+ TRACDCOMP(g_trac_vfs, "VfsRp::verify_page Prev Page vaddr = 0x%llX, index = %d, bin file offset = 0x%llX",
+ l_prevPage,
+ getHashPageTableIndex(l_prevPage,i_baseOffset),
+ l_prevPage+PAGE_SIZE+iv_protectedPayloadSize);
+ PAGE_TABLE_ENTRY_t* l_prevPageTableEntry = getHashPageTableEntry(
+ l_prevPage,
+ i_baseOffset,
+ i_hashPageTableOffset);
+
+ // Concatenate previous page table entry with current page data
+ std::vector< std::pair<void*,size_t> > l_blobs;
+ l_blobs.push_back(std::make_pair<void*,size_t>(l_prevPageTableEntry,
+ HASH_PAGE_TABLE_ENTRY_SIZE));
+ l_blobs.push_back(std::make_pair<void*,size_t>(
+ reinterpret_cast<void*>(l_pnorVaddr),
+ PAGE_SIZE));
+ SHA512_t l_curPageHash = {0};
+ SECUREBOOT::hashConcatBlobs(l_blobs, l_curPageHash);
+
+ // Compare existing hash page table entry with the derived one.
+ if (memcmp(l_pageTableEntry,l_curPageHash,HASH_PAGE_TABLE_ENTRY_SIZE) != 0)
+ {
+ TRACFCOMP(g_trac_vfs, "ERROR:>VfsRp::verify_page secureboot verify fail on vaddr 0x%llX, offset into HBI 0x%llX",
+ i_vaddr,
+ i_vaddr+PAGE_SIZE+iv_protectedPayloadSize);
+ /*@
+ * @severity ERRL_SEV_CRITICAL_SYS_TERM
+ * @moduleid VFS_VERIFY_PAGE
+ * @reasoncode VFS_PAGE_VERIFY_FAILED
+ * @userdata1 Kernel RC
+ * @userdata2 virtual address accessed
+ *
+ * @devdesc Secureboot page verify failure.
+ * @custdesc Corrupted flash image or firmware error during system boot
+ */
+ l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
+ VFS_VERIFY_PAGE,
+ VFS_PAGE_VERIFY_FAILED,
+ TO_UINT64(EACCES),
+ i_vaddr,
+ true);
+ l_errl->collectTrace(VFS_COMP_NAME);
+ l_errl->collectTrace(PNOR_COMP_NAME);
+ }
+
+ return l_errl;
+}
+
+VfsRp& VfsRp::getInstance()
+{
+ return Singleton<VfsRp>::instance();
+}
+
// -- External interface ------------------------------------------------------
errlHndl_t VFS::module_load_unload(const char * i_module, VfsMessages i_msgtype)
@@ -812,5 +936,3 @@ bool VFS::module_is_loaded(const char * i_name)
{
return Singleton<VfsRp>::instance().is_module_loaded(i_name);
}
-
-
diff --git a/src/usr/vfs/vfsrp.H b/src/usr/vfs/vfsrp.H
index ca4d13512..6c1feb7db 100644
--- a/src/usr/vfs/vfsrp.H
+++ b/src/usr/vfs/vfsrp.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2015 */
+/* Contributors Listed Below - COPYRIGHT 2011,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -31,8 +31,11 @@
#include <sys/msg.h>
#include <vector>
#include <sys/sync.h>
+#include <secureboot/service.H>
+// Forward declarations
struct msg_t;
+class SecureRomManagerTest;
namespace VFS
{
@@ -90,7 +93,9 @@ namespace VFS
/**
* Ctor
*/
- VfsRp() : iv_msgQ(NULL), iv_msg(NULL), iv_pnor_vaddr(0)
+ VfsRp() : iv_msgQ(NULL), iv_msg(NULL), iv_pnor_vaddr(0),
+ iv_hashPageTableOffset(0),iv_hashPageTableSize(0),
+ iv_protectedPayloadSize(0),iv_hbExtSecure(0)
{
mutex_init(&iv_mutex);
}
@@ -121,7 +126,7 @@ namespace VFS
/**
* Call _start on module. Montior for crash
* @param[in] i_msg the message
- * @note Does not return.
+ * @note Does not return.
*/
static void* execMonitored(void * i_msg);
@@ -179,16 +184,91 @@ namespace VFS
*/
void _vfsWatcher();
+ /**
+ * Verify page using secure hash page table
+ *
+ * @param[in] i_vaddr address to verify
+ * @param[in] i_baseOffset base offset within a PNOR section
+ * [Default 0 when called within VfsRP.
+ * Fill for test cases]
+ * @param[in] i_hashPageTableOffset hash page table offset based on
+ * iv_pnor_vaddr
+ * [Default 0 when called within VfsRP to
+ * get internal hpt offset. Otherwise
+ * filled in by test cases]
+ *
+ * @return errlog - error log to pass along shutdown path.
+ */
+ errlHndl_t verify_page(uint64_t i_vaddr,
+ uint64_t i_baseOffset = 0,
+ uint64_t i_hashPageTableOffset = 0) const;
+
+ /**
+ * @brief Determines the hash page table index associated with a
+ * vaddr. The hash page table has n-pages + 1 entries.
+ *
+ * @param[in] i_vaddr Vaddr the caller is accessing,
+ * @param[in] i_baseOffset base offset within a PNOR section
+ * [Optional - Used by test cases]
+ *
+ * @return index of the hash page table
+ */
+ inline size_t getHashPageTableIndex (uint64_t i_vaddr,
+ uint64_t i_baseOffset = 0) const
+ {
+ assert(i_baseOffset <= i_vaddr);
+ return ( (i_vaddr - i_baseOffset) / PAGE_SIZE) + 1;
+ }
+
+ /**
+ * @brief Returns a hash page table entry
+ *
+ * @param[in] i_pageTableVaddr Vaddr the caller is accessing
+ * @param[in] i_baseOffset base offset within a PNOR section
+ * [Optional - Used by test cases]
+ * @param[in] i_hashPageTableOffset hash page table offset.
+ * [Default to 0 when called within VfsRP]
+ * Filled in by test cases]
+ *
+ * @return single entry of hash page table
+ */
+ inline PAGE_TABLE_ENTRY_t* getHashPageTableEntry(uint64_t i_vaddr,
+ uint64_t i_baseOffset = 0,
+ uint64_t i_hashPageTableOffset = 0) const
+ {
+ size_t l_index = getHashPageTableIndex(i_vaddr, i_baseOffset);
+ size_t l_offset = l_index * HASH_PAGE_TABLE_ENTRY_SIZE;
+
+ // Decide whether to use the internal or passed in value for
+ // hash page table offset.
+ size_t l_hashPageTableOffset = (i_hashPageTableOffset == 0) ?
+ iv_hashPageTableOffset :
+ iv_pnor_vaddr + i_hashPageTableOffset;
+ return reinterpret_cast<PAGE_TABLE_ENTRY_t*>
+ (l_hashPageTableOffset+l_offset);
+ }
+
private: // data
msg_q_t iv_msgQ; //!< message queue
msg_t* iv_msg; //!< Current message being handled
- uint64_t iv_pnor_vaddr; //!< virtual address of ext image in PFNOR
+ uint64_t iv_pnor_vaddr; //!< virtual address of ext image in PNOR
+ uint64_t iv_hashPageTableOffset; //!< virtual address of hashPageTable of ext image
+ uint64_t iv_hashPageTableSize; //!< size of hashPageTable of ext image
+ uint64_t iv_protectedPayloadSize; //!< size of entire protected payload of ext img
+ //!< Includes Hash page table and VFS module table
+ bool iv_hbExtSecure; //!< cache result if hostboot extended image is secure
typedef std::vector<VfsSystemModule *> ModuleList_t;
mutex_t iv_mutex; //!< lock for iv_loaded
ModuleList_t iv_loaded; //!< Loaded modules
+
+ friend class ::SecureRomManagerTest;
+ /**
+ * @brief Static instance function
+ */
+ static VfsRp& getInstance();
};
}; // VFS namepsace
OpenPOWER on IntegriCloud