diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/CryptoPkg | |
download | zprj-master.tar.xz |
Diffstat (limited to 'Core/EM/CryptoPkg')
-rw-r--r-- | Core/EM/CryptoPkg/CryptLib/Cryptlib.cif | 15 | ||||
-rw-r--r-- | Core/EM/CryptoPkg/CryptLib/cryptlib.chm | bin | 0 -> 82444 bytes | |||
-rw-r--r-- | Core/EM/CryptoPkg/CryptLib/cryptlib.lib | bin | 0 -> 139706 bytes | |||
-rw-r--r-- | Core/EM/CryptoPkg/CryptLib/cryptlib.sdl | 36 | ||||
-rw-r--r-- | Core/EM/CryptoPkg/CryptLib/cryptlibX64.lib | bin | 0 -> 232926 bytes | |||
-rw-r--r-- | Core/EM/CryptoPkg/CryptLib/cryptlibpei.lib | bin | 0 -> 92784 bytes | |||
-rw-r--r-- | Core/EM/CryptoPkg/CryptLib/license.txt | 102 | ||||
-rw-r--r-- | Core/EM/CryptoPkg/CryptoAPI.chm | bin | 0 -> 110686 bytes | |||
-rw-r--r-- | Core/EM/CryptoPkg/CryptoAPI.cif | 16 | ||||
-rw-r--r-- | Core/EM/CryptoPkg/CryptoAPI.mak | 127 | ||||
-rw-r--r-- | Core/EM/CryptoPkg/CryptoAPI.sdl | 95 | ||||
-rw-r--r-- | Core/EM/CryptoPkg/CryptoDxe.c | 1108 | ||||
-rw-r--r-- | Core/EM/CryptoPkg/CryptoDxe.dxs | 53 | ||||
-rw-r--r-- | Core/EM/CryptoPkg/CryptoPei.c | 800 | ||||
-rw-r--r-- | Core/EM/CryptoPkg/CryptoPei.dxs | 54 | ||||
-rw-r--r-- | Core/EM/CryptoPkg/CryptoPkg.cif | 9 |
16 files changed, 2415 insertions, 0 deletions
diff --git a/Core/EM/CryptoPkg/CryptLib/Cryptlib.cif b/Core/EM/CryptoPkg/CryptLib/Cryptlib.cif new file mode 100644 index 0000000..d3f341b --- /dev/null +++ b/Core/EM/CryptoPkg/CryptLib/Cryptlib.cif @@ -0,0 +1,15 @@ +<component> + name = "Crypto LIB" + category = ModulePart + LocalRoot = "Core\EM\CryptoPkg\CryptLib\" + RefName = "CryptoLIB" +[files] +"cryptlib.chm" +"cryptlib.sdl" +"cryptlib.lib" +"cryptlibX64.lib" +"cryptlibpei.lib" +"license.txt" +[parts] +"CryptoLibInc" +<endComponent> diff --git a/Core/EM/CryptoPkg/CryptLib/cryptlib.chm b/Core/EM/CryptoPkg/CryptLib/cryptlib.chm Binary files differnew file mode 100644 index 0000000..9f80f28 --- /dev/null +++ b/Core/EM/CryptoPkg/CryptLib/cryptlib.chm diff --git a/Core/EM/CryptoPkg/CryptLib/cryptlib.lib b/Core/EM/CryptoPkg/CryptLib/cryptlib.lib Binary files differnew file mode 100644 index 0000000..53ce46a --- /dev/null +++ b/Core/EM/CryptoPkg/CryptLib/cryptlib.lib diff --git a/Core/EM/CryptoPkg/CryptLib/cryptlib.sdl b/Core/EM/CryptoPkg/CryptLib/cryptlib.sdl new file mode 100644 index 0000000..8587961 --- /dev/null +++ b/Core/EM/CryptoPkg/CryptLib/cryptlib.sdl @@ -0,0 +1,36 @@ +TOKEN + Name = "CryptLib_SUPPORT" + Value = "1" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +TOKEN + Name = "CRYPTO_trace_level" + Value = "0" + Help = "0-skip debug messages, 1- short trace, 2- full trace" + TokenType = Integer + TargetH = Yes + TargetMAK = Yes + Range = "0-1-2" +End + +TOKEN + Name = "CRYPTOLIB" + Value = "$(Cryptlib_DIR)\CRYPTLIB$(ARCH).lib" + TokenType = "Expression" + TargetMAK = Yes +End + +TOKEN + Name = "CRYPTOLIBPEI" + Value = "$(Cryptlib_DIR)\CRYPTLIBPEI.lib" + TokenType = "Expression" + TargetMAK = Yes +End + +PATH + Name = "Cryptlib_DIR" +End diff --git a/Core/EM/CryptoPkg/CryptLib/cryptlibX64.lib b/Core/EM/CryptoPkg/CryptLib/cryptlibX64.lib Binary files differnew file mode 100644 index 0000000..be4663b --- /dev/null +++ b/Core/EM/CryptoPkg/CryptLib/cryptlibX64.lib diff --git a/Core/EM/CryptoPkg/CryptLib/cryptlibpei.lib b/Core/EM/CryptoPkg/CryptLib/cryptlibpei.lib Binary files differnew file mode 100644 index 0000000..bfad267 --- /dev/null +++ b/Core/EM/CryptoPkg/CryptLib/cryptlibpei.lib diff --git a/Core/EM/CryptoPkg/CryptLib/license.txt b/Core/EM/CryptoPkg/CryptLib/license.txt new file mode 100644 index 0000000..378df36 --- /dev/null +++ b/Core/EM/CryptoPkg/CryptLib/license.txt @@ -0,0 +1,102 @@ +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// Name: License +// Description: WPA Supplicant License +====================================================================== + +Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> and contributors +All Rights Reserved. + +====================================================================== +License +-------- + +This software may be distributed, used, and modified +under the terms of BSD license: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name(s) of the above-listed copyright holder(s) nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +============== +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +====================================================================== + +Features +-------- + +Internal crypto implementation (optional): +- X.509 certificate processing in PEM and DER formats +- PKCS #1 +- ASN.1 +- RSA +- bignum +- minimal size (ca. 50 kB binary, parts of which are already needed for WPA; + TLSv1/X.509/ASN.1/RSA/bignum parts are about 25 kB on x86) + + +Requirements +------------ + +wpa_supplicant was designed to be portable for different drivers and +operating systems. Hopefully, support for more wlan cards and OSes will be +added in the future. See developer's documentation +(http://hostap.epitest.fi/wpa_supplicant/devel/) for more information about the +design of wpa_supplicant and porting to other drivers. One main goal +is to add full WPA/WPA2 support to Linux wireless extensions to allow +new drivers to be supported without having to implement new +driver-specific interface code in wpa_supplicant. + + +WPA +--- + +The original security mechanism of IEEE 802.11 standard was not +designed to be strong and has proven to be insufficient for most +networks that require some kind of security. Task group I (Security) +of IEEE 802.11 working group (http://www.ieee802.org/11/) has worked +to address the flaws of the base standard and has in practice +completed its work in May 2004. The IEEE 802.11i amendment to the IEEE +802.11 standard was approved in June 2004 and published in July 2004. + +Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version of the +IEEE 802.11i work (draft 3.0) to define a subset of the security +enhancements that can be implemented with existing wlan hardware. This +is called Wi-Fi Protected Access<TM> (WPA). This has now become a +mandatory component of interoperability testing and certification done +by Wi-Fi Alliance. Wi-Fi provides information about WPA at its web +site (http://www.wi-fi.org/OpenSection/protected_access.asp). + +IEEE 802.11 standard defined wired equivalent privacy (WEP) algorithm +for protecting wireless networks. WEP uses RC4 with 40-bit keys, +24-bit initialization vector (IV), and CRC32 to protect against packet +forgery. All these choices have proven to be insufficient: key space is +too small against current attacks, RC4 key scheduling is insufficient +(beginning of the pseudorandom stream should be skipped), IV space is +too small and IV reuse makes attacks easier, there is no replay +protection, and non-keyed authentication does not protect against bit +flipping packet data. + +//<AMI_FHDR_END> diff --git a/Core/EM/CryptoPkg/CryptoAPI.chm b/Core/EM/CryptoPkg/CryptoAPI.chm Binary files differnew file mode 100644 index 0000000..7c69ddc --- /dev/null +++ b/Core/EM/CryptoPkg/CryptoAPI.chm diff --git a/Core/EM/CryptoPkg/CryptoAPI.cif b/Core/EM/CryptoPkg/CryptoAPI.cif new file mode 100644 index 0000000..f572730 --- /dev/null +++ b/Core/EM/CryptoPkg/CryptoAPI.cif @@ -0,0 +1,16 @@ +<component> + name = "Crypto Protocol" + category = ModulePart + LocalRoot = "Core\EM\CryptoPkg" + RefName = "CryptoAPI" +[files] +"CryptoAPI.chm" +"CryptoAPI.sdl" +"CryptoAPI.mak" +"CryptoPei.c" +"CryptoDxe.c" +"CryptoPei.dxs" +"CryptoDxe.dxs" +[parts] +"CryptoIncludes" +<endComponent> diff --git a/Core/EM/CryptoPkg/CryptoAPI.mak b/Core/EM/CryptoPkg/CryptoAPI.mak new file mode 100644 index 0000000..f83d42a --- /dev/null +++ b/Core/EM/CryptoPkg/CryptoAPI.mak @@ -0,0 +1,127 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2010, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Modules/CryptoPkg/CryptoAPI.mak 1 6/13/11 5:19p Alexp $ +# +# $Revision: 1 $ +# +# $Date: 6/13/11 5:19p $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Modules/CryptoPkg/CryptoAPI.mak $ +# +# 1 6/13/11 5:19p Alexp +# +# 2 5/11/11 12:59p Alexp +# renamed cryptolib macro name +# +# 1 5/06/11 6:11p Alexp +# initial module release +# +# 5 5/06/11 6:04p Alexp +# link PEI Crypto Lib module +# +# 4 5/06/11 4:39p Alexp +# add help header +# +# 3 4/07/11 12:22p Alexp +# +# 2 4/04/11 7:19p Alexp +# +# 1 3/10/11 4:52p Alexp +# +# 1 2/18/11 5:42p Alexp +# +# +#************************************************************************* +#<AMI_FHDR_START> +# +# Name: CryptoApi.mak +# +# Description: Build rules to build PEI, DXE and SMM Crypto drivers +# +# +#<AMI_FHDR_END> +#************************************************************************* +all : CryptoAPI + +BUILD_CryptoAPI_DIR = $(BUILD_DIR)\$(CryptoAPI_DIR) +BUILD_CryptoAPIIA32_DIR = $(BUILD_DIR)\IA32\$(CryptoAPI_DIR) + +CryptoAPI : CryptLib $(BUILD_DIR)\CryptoAPI.mak CryptoAPIDxeBin \ +!IF "$(CryptoPPI_SUPPORT)" == "1" + CryptoAPIPeiBin +!ENDIF + +#dummy target. Will be used to build Crypto Library if sources are present +CryptLib: + +$(BUILD_DIR)\CryptoAPI.mak : $(CryptoAPI_DIR)\CryptoAPI.cif $(CryptoAPI_DIR)\CryptoAPI.mak $(BUILD_RULES) + $(CIF2MAK) $(CryptoAPI_DIR)\CryptoAPI.cif $(CIF2MAK_DEFAULTS) + +CryptoAPI_PEI_OBJECTS = \ + $(BUILD_CryptoAPIIA32_DIR)\CryptoPei.obj + +CryptoAPI_DXE_OBJECTS = \ + $(BUILD_CryptoAPI_DIR)\CryptoDxe.obj + +CryptoAPI_INCLUDES= \ + /I $(CryptoAPI_DIR)\ + /I $(Cryptlib_DIR)\ + /I $(ReFlash_DIR)\ + /I$(CORE_DIR) + +!IF "$(CryptoPPI_SUPPORT)" == "1" +CryptoAPIPeiBin : $(AMIPEILIB) $(CRYPTOLIBPEI) + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\CryptoAPI.mak all\ + NAME=CryptoPei\ + MAKEFILE=$(BUILD_DIR)\CryptoAPI.mak \ + BUILD_DIR=$(BUILD_DIR)\IA32\ + GUID=D6D2FBA6-EF60-4C38-A83E-6769814D23B0 \ + ENTRY_POINT=CryptoPei_Init \ + "MY_INCLUDES=$(CryptoAPI_INCLUDES)"\ + "CFLAGS=$(CFLAGS) /D PEI_BUILD" \ + OBJECTS="$(CryptoAPI_PEI_OBJECTS)" \ + DEPEX1=$(CryptoAPI_DIR)\CryptoPei.DXS DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \ + TYPE=PEIM COMPRESS=1 +!ENDIF + +CryptoAPIDxeBin : $(AMIDXELIB) $(CRYPTOLIB) + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\CryptoAPI.mak all\ + NAME=CryptoDxe\ + MAKEFILE=$(BUILD_DIR)\CryptoAPI.mak \ + GUID=20D8FFFE-15C3-4ea9-9D28-CFE2745D78F3 \ + ENTRY_POINT=CryptoDxe_Init\ + DEPEX1=$(CryptoAPI_DIR)\CryptoDxe.DXS DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\ + "MY_INCLUDES=$(CryptoAPI_INCLUDES) "\ + OBJECTS="$(CryptoAPI_DXE_OBJECTS)" \ + TYPE=RT_DRIVER COMPRESS=1 + +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2010, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/Core/EM/CryptoPkg/CryptoAPI.sdl b/Core/EM/CryptoPkg/CryptoAPI.sdl new file mode 100644 index 0000000..5e6f9ee --- /dev/null +++ b/Core/EM/CryptoPkg/CryptoAPI.sdl @@ -0,0 +1,95 @@ +TOKEN + Name = "CryptoAPI_SUPPORT" + Value = "1" + Help = "Main switch to enable CryptoAPI support in Project" + TokenType = Boolean + TargetMAK = Yes + TargetH = Yes + Master = Yes +End + +TOKEN + Name = "CryptoPPI_SUPPORT" + Value = "1" + Help = "Includes the Crypto PPI module" + TokenType = Boolean + TargetMAK = Yes + TargetH = Yes +End + +TOKEN + Name = "CR_PEI_MAX_HEAP_SIZE" + Value = "48*1024" + Help = "Crypt Optimized Mem manager. Min 15kb in rsa decrypt in Mode2,(?? if page alligned heap)" + TokenType = Expression + TargetH = Yes +End + +TOKEN + Name = "CR_DXE_MAX_HEAP_SIZE" + Value = "48*1024" + Help = "Crypt Optimized Mem manager. Min 48kb if process PKCS7 Certs and Rsa decrypt in Mode2,(?? if page alligned heap)" + TokenType = Expression + TargetH = Yes +End + +TOKEN + Name = "E_CONST" + Value = "0x01, 0x00, 0x01" + Help = "RSA2048. Predefined value of Public Exponent:E = 0x10001" + TokenType = Expression + TargetH = Yes + Lock = Yes +End + +TOKEN + Name = "PSS_SIG_SALTLEN" + Value = "8" + Help = "PKCS_1 PSS Signature constant. Size of the Salt (random data) field in PSS signature." + TokenType = Integer + TargetH = Yes + Lock = Yes +End + +TOKEN + Name = "CONFIG_PEI_PKCS7" + Value = "0" + Help = "Support x509 & Pkcs7 in PEI CryptoLib. Add ~8kb to CryptoPEI binary" + TokenType = Boolean + TargetMAK = Yes + TargetH = Yes + Range = "0-1" +End + +TOKEN + Name = "PKCS7_MUTEX_LOCK" + Value = "0" + Help = "Turn on mutex functionality for Pkcs7Verify back to back operations. Preserves internal context until mutext released/reset" + TokenType = Boolean + TargetH = Yes + Range = "0-1" +End + +PATH + Name = "CryptoAPI_DIR" + Help = "Path to CryptoAPI Module in Project" +End + +MODULE + Help = "Includes CryptoAP.mak to Project" + File = "CryptoAPI.mak" +End + +ELINK + Name = "$(BUILD_DIR)\CryptoPei.ffs" + Parent = "FV_BB" + InvokeOrder = AfterParent + Token = "CryptoPPI_SUPPORT" "=" "1" +End + +ELINK + Name = "$(BUILD_DIR)\CryptoDxe.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End + diff --git a/Core/EM/CryptoPkg/CryptoDxe.c b/Core/EM/CryptoPkg/CryptoDxe.c new file mode 100644 index 0000000..8c40af1 --- /dev/null +++ b/Core/EM/CryptoPkg/CryptoDxe.c @@ -0,0 +1,1108 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** +//********************************************************************** +// $Header: /Alaska/BIN/Modules/CryptoPkg/CryptoDxe.c 31 8/15/13 9:43a Alexp $ +// +// $Revision: 31 $ +// +// $Date: 8/15/13 9:43a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/BIN/Modules/CryptoPkg/CryptoDxe.c $ +// +// 31 8/15/13 9:43a Alexp +// Pkcs7Verify() - add TimeStamp signature processing(UEFI ECR1009) +// Pkcs7Verify() - enable code branch for PKCS7_MUTEX_LOCK +// +// 30 8/02/13 4:26p Alexp +// Moved EFI_HASH_ALGORITHM_SHA256_NOPAD_GUID under AmiDigSig +// Protocol defining header file +// +// 29 8/02/13 4:00p Alexp +// 1. Fix logic to get FwKey from a Hob. +// Key is copied into pre-allocated buffer by driver entry point +// 2. Optimized Pkcs7Verify. +// +// 27 6/20/13 1:55p Alexp +// Impove FwKey handling. CryptoPEI pass FwKey location to Dxe via Hob +// Add mor parameter checking including +// check for FwKey location to be mapped to Flash FV_BB +// +// 26 1/11/13 10:07a Alexp +// GetKey(): fix MemCpy() 2nd argument. Was not copying a key buffer. +// +// 25 12/28/12 2:50p Alexp +// EIP#110823:The system cannot boot to UEFI(WIN8) OS if the Secure Flash +// Pkg module is not supported +// Update GetKey(); InSmmFunction() and NotInSmmFunction() routines +// to handle cases when Fw Key FFS file not present +// +// 23 12/10/12 6:09p Alexp +// Bug fix: InSmmFunction() the Key pointer gKeyBuf was to updated to Key +// in SMM region +// +// 21 12/07/12 4:08p Alexp +// disable debug crypto traces in SMM +// +// 20 11/29/12 3:10p Alexp +// Pkcs7Verify()- +// Fix error checking for input **Data parameter : Data == NULL +// +// 18 11/16/12 5:10p Alexp +// EIP#105015: Add handling of x509 format for Platform FW Key in FFS +// files +// +// 16 8/28/12 12:33p Alexp +// UEFI 2.3.1. ErrataC. +// Added support for new Hash types +// defined by a GUID with 'NOPAD' keyword: +// EFI_HASH_ALGORITHM_SHA1_NOPAD_GUID +// EFI_HASH_ALGORITHM_SHA256_NOPAD_GUID +// +// 15 8/22/12 4:28p Alexp +// Added support in Pkcs7Parse() for new operations: +// Pkcs7CertValidateGetSignerKey - n-modulus of Signer key +// Pkcs7CertGetMatchInCertChain - true if found leaf cert matching +// to +// trust cert +// Pkcs7CertValidateGetCAKey, - n-modulus of CA key if detected +// in +// x509 chain +// Pkcs7GetCAKey, Pkcs7GetSignerKey +// +// 12 7/23/12 4:12p Alexp +// Pkcs7Verify: +// Bug Fix. For condition:Pkcs7CertValidateGetMatchInCertChain return +// success if leaf cert is found. Before code fell down testing +// certificate and could return error potentially misleading Caller of this +// function. +// +// 11 7/18/12 8:57p Alexp +// Pkcs7Verify +// fix bug - "reason" var was used uninitialized +// +// 10 5/04/12 9:49a Alexp +// [TAG] EIP89280 +// [Category] Improvement +// [Description] When secure boot enable with secure flash disable, in +// Security page of setup menu same items will exist twice +// Fix: Install Crypto Protocols even if Root FW Key not found (brought in +// by Sec Flash module) +// [Files] cryptoDxe.c +// +// 9 4/11/12 5:27p Alexp +// Add new operand within Pkcs7Validate: +// Pkcs7CertValidateGetMatchInCertChain +// +// 7 3/02/12 10:43a Alexp +// Remove dependency on SDL Token FWKEY_FORMAT to determine format of PR +// Key file +// Try different Ffs GUIDs to select proper Key format: SHA or RSA +// +// 6 2/29/12 4:04p Alexp +// 1. Add VerifyKey +// 2. Fix GetKey (API call will be deprecated as not needed) to move PR +// Key from file to local storage +// 3. Use FWKEY_FORMAT to process VerifyKey according to file format. Hash +// input RSA2048 key for comparison if PR Key stored as Hash +// +// 5 11/14/11 12:01p Alexp +// InSmmFunction()->InstallMultipleProtocols() Change the HAndle argument +// from ImageHandle to a DummyHandle=NULL +// +// 4 6/30/11 5:45p Alexp +// GetRawImage: added freepool(HandleBuffer) +// +// 3 6/27/11 5:30p Alexp +// removed commented out lines +// +// 2 6/22/11 5:46p Alexp +// update deafult Crypto trace level +// +// 1 6/13/11 5:19p Alexp +// +// 7 6/10/11 6:21p Alexp +// added new Pkcs7 parse Operation: Pkcs7CertValidateGetSignerKeyHash +// +// 6 6/09/11 9:57a Alexp +// always parse PKCS7 cert +// +// 5 5/18/11 1:18p Alexp +// edited text in func headers +// +// 4 5/17/11 12:53p Alexp +// fix WDK Level4 compiler warnings +// +// 3 5/11/11 7:38p Alexp +// remove set trace level call. If needed, modify Sdl token in Crypto Src +// +// 2 5/10/11 6:55p Alexp +// use external Guid variable declarations +// +// 1 5/06/11 6:11p Alexp +// initial module release +// +// 10 4/22/11 4:20p Alexp +// cleaned up CryptoGetRawImage +// +// 9 4/18/11 7:09p Alexp +// +// 8 4/11/11 12:52p Alexp +// remove ASN1 as possible Key buf format. +// +// 7 4/05/11 6:31p Alexp +// remove content from GetKey. We may add get FwSig key in later +// revisions +// +// 6 3/31/11 6:14p Alexp +// hashing of SpcIndirect data is done inside Pkcs Validate +// +// +//********************************************************************** +#include <Token.h> +#include <AmiDxeLib.h> +#include "Setup.h" +#include "AmiCertificate.h" +#include <Protocol\AmiDigitalSignature.h> +#include <Protocol\Hash.h> + +#include <cryptlib.h> + +#include <Protocol\SmmBase.h> // used for SMM Malloc + +// +// Global variables +// +extern EFI_BOOT_SERVICES *pBS; +extern EFI_RUNTIME_SERVICES *pRS; + +static EFI_GUID gPRKeyGuid = PR_KEY_GUID; + +// The ptr to a buffer containing the Fw Platform Key +// Key Image is copied from .ffs to a local buffer. +// It is a safe location in case of AmiSig running in SMM +static CRYPT_HANDLE gKey = {{0},0,NULL}; + +// Second part of the Public key, public exponent (e), +// must be hardwired in the FW elsewhere(recommended value of e=65537). +// +// SDL Hardwired value of publicExponent--e +const UINT8 KeyE[] = {E_CONST}; // 0x10001 +const UINT32 LenE = sizeof(KeyE); +const INT32 saltlen = PSS_SIG_SALTLEN; // 8 +static UINT8 Rsa2048Sig[DEFAULT_RSA_SIG_LEN]; + +// Pkcs7 Certificate private var +//struct pkcs7_signed_data_st* PKCS7cert = NULL; +// Mutex to control Memory reset during atomic Pkcs7 operations +static UINT8 MutexLock = RESET; + +//---------------------------------------------------------------------------- +// Crypto Function prototypes +//---------------------------------------------------------------------------- +EFI_STATUS +Pkcs1Verify ( + IN CONST AMI_DIGITAL_SIGNATURE_PROTOCOL *This, + IN CRYPT_HANDLE *PublicKey, + IN CRYPT_HANDLE *Hash, + IN VOID *Signature, + IN UINTN SignatureSize, + IN UINT32 Flags + ); + +EFI_STATUS +Pkcs7Verify ( + IN CONST AMI_DIGITAL_SIGNATURE_PROTOCOL *This, + IN CONST UINT8 *P7Data, + IN UINTN P7Size, + IN CONST UINT8 *TrustedCert, + IN UINTN CertSize, + IN OUT UINT8 **Data, + IN OUT UINTN *DataSize, + IN UINT8 Operation, + IN UINT32 Flags + ); + +EFI_STATUS +Hash( + IN CONST AMI_DIGITAL_SIGNATURE_PROTOCOL *This, + IN CONST EFI_GUID *HashAlgorithm, + IN UINTN Num_elem, + IN CONST UINT8 *Addr[], + IN CONST UINTN *Len, + OUT UINT8 *Hash + ); + +EFI_STATUS +GetKey ( + IN CONST AMI_DIGITAL_SIGNATURE_PROTOCOL *This, + OUT CRYPT_HANDLE *Key, + IN EFI_GUID *AlgId, + IN UINTN KeyLen, + IN UINT32 Flags + ); + +EFI_STATUS +VerifyKey ( + IN CONST AMI_DIGITAL_SIGNATURE_PROTOCOL *This, + IN EFI_GUID *AlgId, + IN CRYPT_HANDLE *Key + ); +//---------------------------------------------------------------------------- +// Crypto Protocol Identifiers +//---------------------------------------------------------------------------- +AMI_DIGITAL_SIGNATURE_PROTOCOL mAmiSig = { + Pkcs1Verify, + Pkcs7Verify, + Hash, + GetKey, + VerifyKey +}; + +//---------------------------------------------------------------------------- +// Crypto Function Implementation +//---------------------------------------------------------------------------- + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: Hash +// +// Description: Allows creating a hash of an arbitrary message digest using one or more hash algorithms +// +// Input: +// This Pointer to the AMI_DIGITAL_SIGNATURE_PROTOCOL instance. +// HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use. +// num_elem Number of blocks to be passed via next argument:addr[] +// addr[] Pointer to array of UINT8* addresses of data blocks to be hashed +// len Pointer to array of integers containing length of each block listed by addr[] +// Hash Holds the resulting hash computed from the message. +// +// Output: +// EFI_SUCCESS Hash returned successfully. +// EFI_INVALID_PARAMETER Message or Hash is NULL +// EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this +// driver. +// +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS +Hash( + IN CONST AMI_DIGITAL_SIGNATURE_PROTOCOL *This, + IN CONST EFI_GUID *HashAlgorithm, + IN UINTN num_elem, + IN CONST UINT8 *addr[], + IN CONST UINTN *len, + OUT UINT8 *Hash + ) +{ + BOOLEAN bSha1 = FALSE, bSha256 = FALSE; + UINT32 HashLen=SHA256_DIGEST_SIZE; + +// Support only SHA1 & SHA256 hashes + if(!guidcmp((EFI_GUID*)HashAlgorithm, &gEfiHashAlgorithmSha1Guid) || + !guidcmp((EFI_GUID*)HashAlgorithm, &gEfiHashAlgorithmSha1NoPadGuid)) + { + bSha1 = TRUE; + HashLen = SHA1_DIGEST_SIZE; + } + else + if(!guidcmp((EFI_GUID*)HashAlgorithm, &gEfiHashAlgorithmSha256Guid) || + !guidcmp((EFI_GUID*)HashAlgorithm, &gEfiHashAlgorithmSha256NoPadGuid)) + { + bSha256 = TRUE; + HashLen = SHA256_DIGEST_SIZE; + } + else + return EFI_UNSUPPORTED; + + MemSet(Hash, HashLen, 0); + if(bSha1) + sha1_vector(num_elem, addr, len, Hash); + else + sha256_vector(num_elem, addr, len, Hash); + + return EFI_SUCCESS; +} + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: Pkcs7Verify +// +// Description: Verifies the validity of a PKCS#7 signed data as described in "PKCS #7: Cryptographic +// Message Syntax Standard". +// Function perfors several operations on input Pkcs7 certificate +// based on the input Operation argument +// 1. Verifies validity of the signature contained inside the Certificate +// This function decrypts the signature with the Public key from the Signer certificate +// and then compares the decrypted value to the input Data +// 2. Extracts the Signer certificate in format of x509 +// 3. Extracts Root CA certificate that used to sign the Signer certificate. +// +// Input: +// This Pointer to the AMI_DIGITAL_SIGNATURE_PROTOCOL instance. +// P7Data Pointer to the PKCS#7 DER encoded message to verify. +// P7Size Size of the PKCS#7 message in bytes. +// TrustedCert Pointer to a trusted/root X509 certificate encoded in DER, which +// is used for certificate chain verification. +// CertSize Size of the trusted certificate in bytes. +// Data Pointer to the content to be verified/returned at +// DataSize Size of Data in bytes +// Operation Specifies different tasks to perform: +// 0-Function presence check. Must return EFI_SUCCESS +// 1-Validate Certificate +// 2-Return Signer Certificate in *Data. Performs cert chaining and time based validity tests +// 3-Return Root CA certificate referenced by Signer. Used to compare with Trusted Cert in FW +// 4-Validate Root Certificate +// 5-Validate Signer Certificate Chain +// 6-Return Signature Digest Algorithm +// 7-Validate Certificate, return Root CA Certificate +// 8-Validate Certificate, return Signer Certificate +// 9-Validate Certificate, return Signer Key Hash (SHA256) +// 10-Validate Certificate and return Success if match is found between Trust and any leaf certificates in the Signer chain +// 11-Validate Certificate, return ptr in *Data to n-modulus of a Signer Key +// 12-Return Success if match is found between Trust and any leaf certificates in the Signer chain +// 13-Validate Certificate, return ptr in *Data to n-modulus of a Root CA Key +// 14-Return ptr in *Data to n-modulus of a Root CA Key +// 15-Return ptr in *Data to n-modulus of a Signer Key +// 16-Validate TimeStamp certificate chain in Pkcs7 Certificate +// 17-255 reserved values +// Flags Specifies additional flags to further customize the signing/verifying behavior. +// +// Output: +// EFI_SUCCESS The specified PKCS#7 signed data is valid +// EFI_SECURITY_VIOLATION Invalid PKCS#7 signed data. +// EFI_ACCESS_DENIED The Trusted certificate does not have a match in SignedData.certificate store. +// EFI_INVALID_PARAMETER The size of input message or signature does not meet the criteria +// of the underlying signature algorithm. +// +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS +Pkcs7Verify ( + IN CONST AMI_DIGITAL_SIGNATURE_PROTOCOL *This, + IN CONST UINT8 *P7Data, + IN UINTN P7Size, + IN CONST UINT8 *TrustedCert, + IN UINTN CertSize, + IN OUT UINT8 **Data, + IN OUT UINTN *DataSize, + IN UINT8 Operation, + IN UINT32 Flags + ) +{ + EFI_STATUS Status; + INTN err, reason; + static struct pkcs7_signed_data_st* PKCS7cert; + struct x509_certificate *x509SignCert; + struct x509_certificate *x509TrustCert; + UINT8 *x509SignCertPtr, *x509RootCertPtr; + UINTN SignCert_len, CARootCert_len; + struct pkcs7_cert_revoke_info revokeInfo; + EFI_CERT_X509_SHA256 *revokeCert; + +// Mutex functionality: +/* +Structure mutex +Mutual exclusion (mutex) semaphore locking mechanism used to serialise interthread intraprocess activities. +*/ +#if PKCS7_MUTEX_LOCK == 1 + switch(Flags & 0x3) { + case RESET: + ResetCRmm(); // first time needs mem clean + MutexLock = RESET; + PKCS7cert = NULL; + break; + + case LOCK: + ResetCRmm(); // first time needs mem clean + MutexLock = LOCK; + PKCS7cert = NULL; + break; + + case RELEASE: // clear memory after execute routines + if(MutexLock == RESET) + ResetCRmm(); + MutexLock = RESET; + break; + + case KEEP: + if(MutexLock == RESET) + ResetCRmm(); + break; + + default: + ResetCRmm(); + } +#else + PKCS7cert = NULL; + ResetCRmm(); +#endif +/* + Notes of implementation: + + IN order to allocate the Pool for returned Cert (Signer or CA) + -run getCert with Size 0 -> it will return real cert size + -allocate buffer of Size and re-run with new size + OR caller is responsible for freeng the Data buffer + OR caller always allocates sufficient size == Trusted Cert + 1k + + GetSignerCert + parse Pkcs7 to *Pkcs7cert + get SignerName from SignerInfo.serialName + find x509 cert matching Signer name + GetCACert + run GetSignerCert + run cert chain valid for that cert + + ValidateSignCert - internal Cert validation, returns Root CA Cert ptr + ValidateTrustCert - external Trust Cert validation, returns Sign Cert ptr + +*/ + err = -1; + reason=0; + + switch(Operation){ + case Pkcs7Arg0: + Status = EFI_SUCCESS; + err = 0; + break; +// Validate Digest and returns Root CA cert or Signer Cert + case Pkcs7CertGetMatchInCertChain: + case Pkcs7CertValidateGetMatchInCertChain: // obsolete + reason = -1; // non-0 reason argument forces Pkcs7_Chain_Validate to scan for matching Cert in the Chain if other checks failed + case Pkcs7CertValidate: + case Pkcs7CertValidateGetCAKey: + case Pkcs7CertValidateGetCACert: + case Pkcs7CertValidateGetSignerKey: + case Pkcs7CertValidateGetSignerCert: + case Pkcs7CertValidateGetSignerKeyHash: + case Pkcs7TimeStampCertValidateGet: + if(Data == NULL || DataSize == NULL) + break; + case Pkcs7ValidateRootCert: + if (!PKCS7cert) PKCS7cert = Pkcs7_parse_Authenticode_certificate(P7Data, P7Size); + if (!PKCS7cert) + break; + // verify Pkcs7 Signing Cert chain up to the TrustCert...if provided + if(TrustedCert && CertSize) { + x509TrustCert = x509_certificate_parse(TrustedCert, CertSize); + if(x509TrustCert) { + err = Pkcs7_x509_certificate_chain_validate_with_timestamp(PKCS7cert, (Operation == Pkcs7TimeStampCertValidateGet), x509TrustCert, NULL, (int*)&reason); + } else { + // potentially a TimeStamped revocation cert + revokeCert = (EFI_CERT_X509_SHA256*)TrustedCert; + if(CertSize == sizeof(EFI_CERT_X509_SHA256)) + revokeInfo.ToBeSignedHashLen = 32; + else + if(CertSize == sizeof(EFI_CERT_X509_SHA384)) + revokeInfo.ToBeSignedHashLen = 48; + else + if(CertSize == sizeof(EFI_CERT_X509_SHA512)) + revokeInfo.ToBeSignedHashLen = 64; + else { // unsupported Hash struct + err = -1; + break; + } + revokeInfo.ToBeSignedHash = (UINT8*)&revokeCert->ToBeSignedHash; + err = Pkcs7_x509_certificate_chain_validate_with_timestamp(PKCS7cert, FALSE, NULL, &revokeInfo, (int*)DataSize); + } + + if(err == -1 || + Operation==Pkcs7CertGetMatchInCertChain || + Operation == Pkcs7ValidateRootCert + ) + break; // break(err=0) if leaf found to match trust cert + } + // x509SignCert== NULL -> extract SignCert from Pkcs7 crt + err = Pkcs7_certificate_validate_digest(PKCS7cert, NULL, (UINT8*)*Data, (UINTN)*DataSize); + if(!err) { + switch(Operation){ + //Returns CA Root cert after successfully validating Cert chain and signature digest + case Pkcs7CertValidateGetCACert: + err = Pkcs7_return_cerificate_ptr(PKCS7cert, Data, DataSize, &x509SignCertPtr, (size_t*)&SignCert_len); + break; + //Returns Signing Key from Cert after successfully validating Cert chain and signature digest + case Pkcs7CertValidateGetSignerCert: + err = Pkcs7_return_cerificate_ptr(PKCS7cert, &x509RootCertPtr, (size_t*)&CARootCert_len, Data, DataSize); + break; + case Pkcs7CertValidateGetSignerKeyHash: + err = Pkcs7_x509_return_signing_Key(PKCS7cert, &x509SignCertPtr, &SignCert_len); + if(!err) { + Hash(This, &gEfiHashAlgorithmSha256Guid, 1, &x509SignCertPtr, (const UINTN*)&SignCert_len, *Data); + *DataSize=SHA256_DIGEST_SIZE; + } + break; + case Pkcs7CertValidateGetSignerKey: + err = Pkcs7_x509_return_signing_Key(PKCS7cert, Data, DataSize); + break; + case Pkcs7CertValidateGetCAKey: + err = Pkcs7_return_cerificate_ptr(PKCS7cert, Data, DataSize, &x509SignCertPtr, (size_t*)&SignCert_len); + if(!err) + err = Pkcs7_x509_return_Cert_pubKey(*Data, *DataSize, Data, DataSize); + break; + case Pkcs7TimeStampCertValidateGet: + err = Pkcs7_certificate_validate_timestamp_digest(PKCS7cert, (long*)DataSize); + break; + } + } + break; + +// returns Ptr within input P7Data DER buffer to RootCA cert or Signing Cert + case Pkcs7GetSignerCert: + case Pkcs7GetCACert: + case Pkcs7GetSignerKey: + case Pkcs7GetCAKey: + if(Data == NULL || DataSize == NULL) { + break; + } + if (!PKCS7cert) PKCS7cert = Pkcs7_parse_Authenticode_certificate(P7Data, P7Size); + if (PKCS7cert) { + err = Pkcs7_return_cerificate_ptr(PKCS7cert, &x509RootCertPtr, (size_t*)&CARootCert_len, &x509SignCertPtr, (size_t*)&SignCert_len); + if(!err) { + switch(Operation){ + case Pkcs7GetSignerCert: + *DataSize = SignCert_len; + *Data = x509SignCertPtr; + break; + case Pkcs7GetCACert: + *DataSize = CARootCert_len; + *Data = x509RootCertPtr; + break; + case Pkcs7GetCAKey: + err = Pkcs7_x509_return_Cert_pubKey(x509RootCertPtr, CARootCert_len, Data, DataSize); + break; + case Pkcs7GetSignerKey: + err = Pkcs7_x509_return_Cert_pubKey(x509SignCertPtr, SignCert_len, Data, DataSize); + break; + } + } + } + break; + + case x509ValidateCertChain: + //Validates Signer certificate's key against Trusted Cert + x509SignCert = x509_certificate_parse(P7Data, P7Size); + if(TrustedCert && CertSize) + x509TrustCert = x509_certificate_parse(TrustedCert, CertSize); + if (x509TrustCert && x509SignCert) + err = x509_certificate_chain_validate(x509TrustCert, x509SignCert, (int*)&reason); + break; + + case Pkcs7GetDigestAlgorithm: + // validate input params. + if(Data == NULL || DataSize == NULL) { + break; + } + if (!PKCS7cert) PKCS7cert = Pkcs7_parse_Authenticode_certificate(P7Data, P7Size); + if (PKCS7cert) { + err = Pkcs7_return_digestAlgorithm(PKCS7cert, (UINT8*)*Data); + if(!err) + *DataSize = sizeof(UINT8); + } + break; + + default: + Status = EFI_INVALID_PARAMETER; + err = -1; + } + +// Security concern, memory heap is being cleared on exit + if(err) + MutexLock = RESET; + +#if PKCS7_MUTEX_LOCK == 1 + if(MutexLock == RESET) +#endif + { + ResetCRmm(); + PKCS7cert = NULL; + } + +// failed to process + Status = !err ? EFI_SUCCESS:EFI_SECURITY_VIOLATION; + + return Status; +} + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: Pkcs1Verify +// +// Description: Function verifies that the specified signature matches the specified hash. +// Verifies the RSA-SSA signature with EMSA-PKCS1-v1_5 encoding scheme defined in +// RSA PKCS#1. +// This function decrypts the signature with the provided key and then compares +// the decrypted value to the specified hash value +// +// Input: +// This Pointer to the AMI_DIGITAL_SIGNATURE_PROTOCOL instance. +// PublicKey Handle to a key used for verifying signatures. This handle must be identifying a public key. +// Hash Handle of the hash object to verify. +// Signature Pointer to the signature data to be verified. +// SignatureSize The size, in bytes, of the signature data. +// Flags Specifies additional flags to further customize the signing/verifying behavior. +// +// Output: +// EFI_SUCCESS The signature is successfully verified. +// EFI_SECURITY_VIOLATION The signature does not match the given message. +// EFI_ACCESS_DENIED The key could not be used in signature operation. +// EFI_INVALID_PARAMETER The size of input message or signature does not meet the criteria +// of the underlying signature algorithm. +// +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS +Pkcs1Verify ( + IN CONST AMI_DIGITAL_SIGNATURE_PROTOCOL *This, + IN CRYPT_HANDLE *PublicKey, + IN CRYPT_HANDLE *Hash, + IN VOID *Signature, + IN UINTN SignatureSize, + IN UINT32 Flags + ) +{ + EFI_STATUS Status; + INTN err; + struct crypto_rsa_key *key = NULL; + UINT16 Size = (UINT16)(PublicKey->BlobSize); + size_t *sig_len=(size_t*)&SignatureSize; + INT32 modulus_bitlen = DEFAULT_RSA_SIG_LEN << 3; + UINT32 HashLen; + +// Only supporting RSASSA_PKCS1V15 & PSS signature types + if(!((Flags & EFI_CRYPT_RSASSA_PKCS1V15) || + (Flags & EFI_CRYPT_RSASSA_PSS)) ) + return EFI_INVALID_PARAMETER; + + if(!PublicKey || !Hash || !Signature) + return EFI_INVALID_PARAMETER; + + ResetCRmm(); + MutexLock = RESET; + +// For now Public Key is supported in 2 formats: RAW 256 bytes and ASN.1 Integer + if(!guidcmp(&PublicKey->AlgGuid, &gEfiCertRsa2048Guid)) + key = crypto_import_rsa2048_public_key(PublicKey->Blob, Size, (UINT8*)&KeyE, LenE); + else + return EFI_INVALID_PARAMETER; + +// 2 hash types supporte: SHA1 & SHA256 + if(!guidcmp(&Hash->AlgGuid, &gEfiHashAlgorithmSha256Guid)) + HashLen = SHA256_DIGEST_SIZE; + else if(!guidcmp(&Hash->AlgGuid, &gEfiHashAlgorithmSha1Guid)) + HashLen = SHA1_DIGEST_SIZE; + else + HashLen = SHA256_DIGEST_SIZE; + + if(key == NULL ) + err = -1; + else + err = crypto_rsa_exptmod((const UINT8*)Signature, (size_t)SignatureSize, (UINT8*)&Rsa2048Sig, sig_len, key, 0); + +// locate Hash inside the decrypted signature body and compare it with given Hash; + if(!err) { + if(Flags & EFI_CRYPT_RSASSA_PKCS1V15) + { + // Validate PKCS#1 Padding +// err = pkcs_1_v1_5_decode((const UINT8 *)&Hash->Blob, HashLen, (const UINT8 *)&Rsa2048Sig, (unsigned long)*sig_len); + err = MemCmp((void*)(UINTN)Hash->Blob, (void*)(UINTN)((UINT32)(UINTN)Rsa2048Sig + (UINT32)(*sig_len - HashLen)), HashLen); + } + else //(Flags & EFI_CRYPT_RSASSA_PSS)) + // Validate PKCS_1 PSS Signature: padding & hash + err = pkcs_1_pss_decode((UINT8*)Hash->Blob, HashLen,(const unsigned char *)&Rsa2048Sig, (unsigned long)*sig_len, + saltlen, modulus_bitlen); + } + + Status = !err ? EFI_SUCCESS:EFI_SECURITY_VIOLATION; + +// Security concern, memory heap is being cleared on exit + ResetCRmm(); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// Procedure: CryptoGetFwKey +// +// Description: Passes FwKey info from a Hob to an external Key handler structure +// +// Input: Key - ptr to the buffer to hold the target key parameters +// +// Output: Status +// +// EFI_NOT_FOUND - Can't find the Key Hob +// EFI_INVALID_PARAMETER - Wrong KeyID +// EFI_LOAD_ERROR - Load fail. +// EFI_SUCCESS - Load success. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +CryptoGetFwKey ( + IN EFI_SYSTEM_TABLE *SystemTable, + IN CRYPT_HANDLE *Key +) +{ + EFI_STATUS Status=EFI_NOT_FOUND; + FW_KEY_HOB *pFwKeyHob; + static EFI_GUID HobListGuid = HOB_LIST_GUID; + + if(!Key) return EFI_INVALID_PARAMETER; + + pFwKeyHob = GetEfiConfigurationTable(SystemTable, &HobListGuid); + if (pFwKeyHob!=NULL) { + Status = FindNextHobByGuid(&gPRKeyGuid, &pFwKeyHob); + if(!EFI_ERROR(Status)) { +// make sure the Key buffer is mapped to FV_BB address space +/* + if(!((UINT32)pFwKeyHob->KeyAddress > FV_BB_BASE && + (UINT64)((UINT32)pFwKeyHob->KeyAddress+pFwKeyHob->KeySize) < + (UINT64)(FV_BB_BASE+(UINT64)FV_BB_BLOCKS*FLASH_BLOCK_SIZE))) { + return EFI_NOT_FOUND; +*/ + Key->Blob = (UINT8*)(UINT32)pFwKeyHob->KeyAddress; + Key->BlobSize = pFwKeyHob->KeySize; + Key->AlgGuid = pFwKeyHob->KeyGuid; + } + } + + TRACE(((UINTN) -1,"Get Key File %g: %r\n(%lx, %dbytes)=%X,%X\n", Key->AlgGuid, Status, Key->Blob, Key->BlobSize, Key->Blob[0], Key->Blob[1])); + + return Status; +} +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: GetKey +// +// Description: Return Firmware Signing Key from a local storage +// +// Input: +// This Pointer to the AMI_DIGITAL_SIGNATURE_PROTOCOL instance. +// Key ptr to the buffer to hold the target key +// AlgId Key GUID +// KeyLen Length of the target Key buffer +// Flags Specifies additional flags to further customize the GetKey behavior. +// Output: +// EFI_SUCCESS +// EFI_ACCESS_DENIED The key could not be located +// EFI_INVALID_PARAMETER Wrong KeyID +// BUFFER_TOO_SMALL The Key->BlobSize will contain the size of the buffer to be prepared +// +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS +GetKey ( + IN CONST AMI_DIGITAL_SIGNATURE_PROTOCOL *This, + OUT CRYPT_HANDLE *Key, + IN EFI_GUID *AlgId, + IN UINTN KeyLen, + IN UINT32 Flags + ) +{ + if(!AlgId || !Key) + return EFI_INVALID_PARAMETER; + +// Guid must match one of the valid keys we can use in Sig verification. + if(guidcmp(AlgId, &gPRKeyGuid)) + return EFI_UNSUPPORTED; + + if(gKey.Blob && gKey.BlobSize){ + +// make sure the Key buffer is mapped to FV_BB address space +/* if(!((UINT32)gKey.Blob > FV_BB_BASE && + (UINT64)((UINT32)gKey.Blob+gKey.BlobSize) < + (UINT64)(FV_BB_BASE+(UINT64)FV_BB_BLOCKS*FLASH_BLOCK_SIZE))) + return EFI_NOT_FOUND; +*/ + Key->BlobSize = gKey.BlobSize; + Key->AlgGuid = gKey.AlgGuid; + if(Key->Blob) { + if(KeyLen < gKey.BlobSize) + return EFI_BUFFER_TOO_SMALL; + else + MemCpy(Key->Blob, gKey.Blob, gKey.BlobSize); + } else + Key->Blob = gKey.Blob;// upd address to int buffer + + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: VerifyKey +// +// Description: Function compares the input PublicKey against +// Platform Signing Key (PK) image in the flash. +// +// Input: +// This Pointer to the AMI_DIGITAL_SIGNATURE protocol instance. +// KeyAlgorithm Points to the EFI_GUID which identifies the PKpub algorithm to use. +// PublicKey Handle to a key used for verifying signatures. This handle must be identifying a public key. +// +// Output: +// EFI_SUCCESS The Key is successfully verified. +// EFI_SECURITY_VIOLATION The Key does not match current FW key. +// EFI_ACCESS_DENIED The key could not be used in signature operation. +// EFI_INVALID_PARAMETER The size of input message or signature does not meet the criteria +// of the underlying signature algorithm. +// +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS +VerifyKey ( + IN CONST AMI_DIGITAL_SIGNATURE_PROTOCOL *This, + IN EFI_GUID *AlgId, + IN CRYPT_HANDLE *Key + ) +{ + EFI_STATUS Status; + CRYPT_HANDLE PubKeyHndl; + UINT8 Hash[SHA256_DIGEST_SIZE]={0}; + UINT8 *KeyFfs, *KeyCmp; + UINTN KeyLen; + UINT32 Flags=0; + INTN err; + + if(!AlgId || !Key || !Key->Blob) + return EFI_INVALID_PARAMETER; + +// Guid must match one of the valid keys we can use in Sig verification. + if(guidcmp(AlgId, &gPRKeyGuid)) + return EFI_UNSUPPORTED; + +// Get PRKey + PubKeyHndl.Blob = NULL; + PubKeyHndl.BlobSize = 0; + Status = GetKey(NULL, &PubKeyHndl, AlgId, 0, Flags); + if(!EFI_ERROR(Status)) + { + KeyFfs = PubKeyHndl.Blob; + KeyLen = PubKeyHndl.BlobSize; + KeyCmp = Key->Blob; + + // If FwKey is Hash of Rsa2048 Key and Key->Algo is Rsa2048 - + // prepare Key for SHA256 Hash compare + if(!guidcmp(&Key->AlgGuid, &gEfiCertRsa2048Guid)) + { + if(!guidcmp(&PubKeyHndl.AlgGuid, &gEfiCertSha256Guid)) + { + KeyCmp = Hash; + KeyLen = SHA256_DIGEST_SIZE; + sha256_vector(1, (const UINT8**)&Key->Blob, (const UINTN*)&Key->BlobSize, Hash); + } else + // if FwKey is x509 and Key->Algo - gEfiCertRsa2048Guid: + // derive nModulus from x509 Key Cert for comparison + if(!guidcmp(&PubKeyHndl.AlgGuid, &gEfiCertX509Guid)) + { + KeyFfs = &Rsa2048Sig[0]; + KeyLen = DEFAULT_RSA_KEY_MODULUS_LEN; + ResetCRmm(); + err = Pkcs7_x509_return_Cert_pubKey((UINT8*)PubKeyHndl.Blob, (UINTN)PubKeyHndl.BlobSize, &KeyFfs,&KeyLen); + ResetCRmm(); + if(err) return EFI_SECURITY_VIOLATION; + } + } + err = MemCmp(KeyFfs, KeyCmp, KeyLen); + + Status = !err ? EFI_SUCCESS:EFI_SECURITY_VIOLATION; + } + return Status; +} +//---------------------------------------------------------------------------- +// END of Crypto DXE Function definitions +//---------------------------------------------------------------------------- + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// Procedure: InSmmFunction +// +// Description: +// +// Input: +// +// Output: +// +// Returns: +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS InSmmFunction(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_STATUS Status; + EFI_HANDLE DummyHandle = NULL; + UINT8 *pKey; + + TRACE(((UINTN) -1,"Init Crypto API in SMM\n")); + // + // Init Crypto lib internal state + // + RuntimeCryptLibConstructorInSmm(ImageHandle, SystemTable); + // + // Update Crypto debug traces level + // +#ifdef EFI_DEBUG +// wpa_set_trace_level(CRYPTO_trace_level); +#endif + // + // Get location of PRKey from .ffs + // ReadFfs/FindHob are preboot services whereas Key needs to be available during EFI runtime + // + gKey.Blob = NULL; + Status = CryptoGetFwKey(SystemTable, &gKey); + if(!EFI_ERROR(Status) && gKey.Blob) { + // re-allocate buffer in runtime mem + pKey = gKey.Blob; // preserve the pointer + Status = pSmmBase->SmmAllocatePool(pSmmBase, EfiRuntimeServicesData, gKey.BlobSize, (void**)&pKey); + ASSERT_EFI_ERROR (Status); + if(!EFI_ERROR(Status)) { + MemCpy(pKey, gKey.Blob, gKey.BlobSize); + gKey.Blob = pKey; + } + } + if(EFI_ERROR(Status)) + gKey.Blob = NULL; + + TRACE((TRACE_ALWAYS,"Init: GetKey %r (addr %x(%X, %X), %d bytes)\n", Status, gKey.Blob, gKey.Blob[0], gKey.Blob[1], gKey.BlobSize)); + +/////////////////////////////////////////////////////////////////////////////////// +// Install the SMM clone of Crypto protocols +/////////////////////////////////////////////////////////////////////////////////// + return pBS->InstallMultipleProtocolInterfaces ( + &DummyHandle, + &gAmiSmmDigitalSignatureProtocolGuid, &mAmiSig, + NULL + ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: NotInSmmFunction +// +// Description: This function is called from outside of SMM during SMM registration. +// +// Input: +// IN EFI_HANDLE ImageHandle +// IN EFI_SYSTEM_TABLE *SystemTable +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NotInSmmFunction(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_STATUS Status; + UINT8 *pKey; + + TRACE(((UINTN) -1,"Init Crypto API NOT in SMM\n")); + // + // Init Crypto lib internal state + // + RuntimeCryptLibConstructor(ImageHandle, SystemTable); + // + // Update Crypto debug traces level + // +#ifdef EFI_DEBUG + wpa_set_trace_level(CRYPTO_trace_level); +#else + wpa_set_trace_level(0); +#endif + // + // Get location of PRKey from .ffs + // ReadFfs/FindHob are preboot services whereas Key needs to be available during EFI runtime + // + gKey.Blob = NULL; + Status = CryptoGetFwKey(SystemTable, &gKey); + if(!EFI_ERROR(Status) && gKey.Blob) { + // re-allocate buffer in runtime mem + pKey = gKey.Blob; // preserve the pointer + Status = pBS->AllocatePool(EfiRuntimeServicesData, gKey.BlobSize, (void**)&pKey); + ASSERT_EFI_ERROR (Status); + if(!EFI_ERROR(Status)) { + MemCpy(pKey, gKey.Blob, gKey.BlobSize); + gKey.Blob = pKey; + } + } + if(EFI_ERROR(Status)) + gKey.Blob = NULL; + + TRACE((TRACE_ALWAYS,"Init: GetKey %r (addr %x(%X, %X), %d bytes)\n", Status, gKey.Blob, gKey.Blob[0], gKey.Blob[1], gKey.BlobSize)); + + +/////////////////////////////////////////////////////////////////////////////// +// +// Install the DXE Crypto protocols +// +/////////////////////////////////////////////////////////////////////////////// + return pBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gAmiDigitalSignatureProtocolGuid, &mAmiSig, + NULL + ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CryptoDxe_Init +// +// Description: Entry point of Crypto DXE driver +// +// Input: EFI_HANDLE ImageHandle, +// EFI_SYSTEM_TABLE *SystemTable +// +// Output: EFI_STATUS +// +// Modified: +// +// Referrals: +// +// Notes: +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +CryptoDxe_Init ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable +) +{ + InitAmiLib(ImageHandle, SystemTable); + // + // Install DXE & SMM Crypto Services + // + + return InitSmmHandler(ImageHandle, SystemTable, InSmmFunction, NotInSmmFunction); +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CryptoPkg/CryptoDxe.dxs b/Core/EM/CryptoPkg/CryptoDxe.dxs new file mode 100644 index 0000000..ba16a62 --- /dev/null +++ b/Core/EM/CryptoPkg/CryptoDxe.dxs @@ -0,0 +1,53 @@ +//**************************************************************************** +//**************************************************************************** +//** ** +//** (C)Copyright 1985-2008, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone (770)-246-8600 ** +//** ** +//**************************************************************************** +//**************************************************************************** +//********************************************************************** +// $Header: /Alaska/BIN/Modules/CryptoPkg/CryptoDxe.dxs 1 6/13/11 5:19p Alexp $ +// +// $Revision: 1 $ +// +// $Date: 6/13/11 5:19p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/BIN/Modules/CryptoPkg/CryptoDxe.dxs $ +// +// 1 6/13/11 5:19p Alexp +// +// 1 5/06/11 6:11p Alexp +// initial module release +// +// 1 3/10/11 4:52p Alexp +// +// 1 2/18/11 5:42p Alexp +// +//********************************************************************** +#include <Protocol/SmmBase.h> + +DEPENDENCY_START + EFI_SMM_BASE_PROTOCOL_GUID +DEPENDENCY_END + +//**************************************************************************** +//**************************************************************************** +//** ** +//** (C)Copyright 1985-2008, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone (770)-246-8600 ** +//** ** +//**************************************************************************** +//**************************************************************************** diff --git a/Core/EM/CryptoPkg/CryptoPei.c b/Core/EM/CryptoPkg/CryptoPei.c new file mode 100644 index 0000000..1945986 --- /dev/null +++ b/Core/EM/CryptoPkg/CryptoPei.c @@ -0,0 +1,800 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** +//********************************************************************** +// $Header: /Alaska/BIN/Modules/CryptoPkg/CryptoPei.c 15 8/01/13 6:27p Alexp $ +// +// $Revision: 15 $ +// +// $Date: 8/01/13 6:27p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/BIN/Modules/CryptoPkg/CryptoPei.c $ +// +// 15 8/01/13 6:27p Alexp +// Comment out a check for FwKey location to be mapped to Flash FV_BB +// In some cases FindFFS for FwKey may return a location outside of Flash +// space. +// Will have the logic fixed in the next label. +// +// 14 7/01/13 5:24p Alexp +// CryptoPei_Init(): fix addr typecasting for pFwKeyHob->KeyAddress +// +// 13 6/20/13 1:55p Alexp +// Impove FwKey handling. CryptoPEI pass FwKey location to Dxe via Hob +// Add mor parameter checking including +// check for FwKey location to be mapped to Flash FV_BB +// +// 12 5/23/13 12:04p Alexp +// Add dependency on PKCS7_PEI_Support switch to turn off Pkcs7 support in +// CryptoPEI. Saves ~8kb of space +// +// 11 12/28/12 3:05p Alexp +// CryptoGetRawImage(): calculate raw Key size inside FwKey ffs file +// +// 10 12/19/12 10:31a Alexp +// code modify to meet "cppcheck" style & performance suggestions +// +// 8 11/15/12 9:28a Alexp +// update Pkcs7Verify help header +// +// 7 11/14/12 6:28p Alexp +// rename ppPS to gPeiServices in order to keep backward compatibility for +// older Secure Flash eModules +// +// 6 11/13/12 11:50a Alexp +// EIP#105015: Add Pkcs#7 Cert Verification function in Crypto PPI +// Add handling of x509 formatted FW Key in FFS files +// +// 5 7/25/12 10:00a Alexp +// cleaned comments in Hash Hdr +// +// 4 3/12/12 4:11p Alexp +// do not install Crypto PPI on S3 resume. +// +// 3 3/02/12 10:43a Alexp +// Remove dependency on SDL Token FWKEY_FORMAT to determine format of PR +// Key file +// Try different Ffs GUIDs to select proper Key format: SHA or RSA +// +// 2 2/29/12 4:01p Alexp +// 1. Use SDL Token FWKEY_FORMAT to define format of PR Key file: Hash or +// RSA2048 +// 2. Modify VerifyKey to account for PR Key in SHA256 format +// +// 1 6/13/11 5:19p Alexp +// +// 1 5/06/11 6:11p Alexp +// initial module release +// +// 10 4/22/11 4:19p Alexp +// fix GetRaw file +// +// 9 4/18/11 7:09p Alexp +// +// 8 4/11/11 12:53p Alexp +// remove Verify Capsule from Crypto PPI. Function moved to SecRecovery.c +// +// 7 4/08/11 1:33p Alexp +// This revision Supports single PK(FwSign) Ffs file with SigDb with +// multiple Keys +// +// 6 4/05/11 6:31p Alexp +// +// 5 3/21/11 6:58p Alexp +// +// 4 3/15/11 12:48p Alexp +// +// 3 3/14/11 3:26p Alexp +// add provision to handle multiple Platform Signing keys. +// rom may containg multiple Keys as FFS files with same Guid +// +// 2 3/11/11 6:51p Alexp +// +// 1 3/10/11 4:52p Alexp +// +// 2 2/28/11 6:46p Alexp +// +// 1 2/18/11 5:42p Alexp +// +//********************************************************************** +#include <Token.h> +#include <AmiPeiLib.h> +#include "PPI\LoadFile.h" +#include <Protocol\Hash.h> +#include <PPI\CryptoPPI.h> +#include "AmiCertificate.h" + +#include <cryptlib.h> + +// +// Global variables +// + +// Although ShaXXXGuid global variables are defined in EDK's EdkProtocol Lib, but linking it adds additional 20k in debug mode. +static EFI_GUID gEfiHashAlgorithmSha1Guid = EFI_HASH_ALGORITHM_SHA1_GUID; +static EFI_GUID gEfiHashAlgorithmSha256Guid = EFI_HASH_ALGORITHM_SHA256_GUID; +static EFI_GUID gPKeyGuid = PR_KEY_GUID; + +// Hardwired at Build time. Supported formats: RSA2048, HASH256 Key Certs +static EFI_GUID gPKeyFileRsa2048Guid = PR_KEY_FFS_FILE_RAW_GUID; +static EFI_GUID gPKeyFileSha256Guid = PR_KEY_FFS_FILE_SHA256_GUID; +static EFI_GUID gPKeyFileX509Guid = PR_KEY_FFS_FILE_X509_GUID; + +static EFI_GUID gEfiCertSha256Guid = EFI_CERT_SHA256_GUID; +static EFI_GUID gEfiCertRsa2048Guid = EFI_CERT_RSA2048_GUID; +static EFI_GUID gEfiCertX509Guid = EFI_CERT_X509; + +static EFI_GUID *gKeyFileGuid [] = { + &gPKeyFileX509Guid, + &gPKeyFileRsa2048Guid, + &gPKeyFileSha256Guid, + NULL +}; +static EFI_GUID *gKeyTypeGuid [] = { + &gEfiCertX509Guid, + &gEfiCertRsa2048Guid, + &gEfiCertSha256Guid, + NULL +}; + +EFI_PEI_SERVICES **gPeiServices; +FW_KEY_HOB *pFwKeyHob = NULL; +// +// SDL defined Public Exponent E of RSA Key. +// +const UINT8 KeyE[] = {E_CONST}; // 0x10001 +const UINT32 LenE = sizeof(KeyE); +// PKCS_1 PSS Signature constatnt. Size of the Salt (random data) field in PSS signature. +const INT32 saltlen = PSS_SIG_SALTLEN; // 8 +static UINT8 DecriptedSig[DEFAULT_RSA_SIG_LEN]; +//---------------------------------------------------------------------------- +// Crypto Function prototypes +//---------------------------------------------------------------------------- +EFI_STATUS +PeiHash ( + IN CONST AMI_CRYPT_DIGITAL_SIGNATURE_PPI *This, + IN CONST EFI_GUID *HashAlgorithm, + IN UINTN num_elem, + IN CONST UINT8 *addr[], + IN CONST UINTN *len, + OUT UINT8 *Hash + ); + +EFI_STATUS +PeiPkcs7Verify ( + IN CONST AMI_CRYPT_DIGITAL_SIGNATURE_PPI *This, + IN CONST UINT8 *P7Data, + IN UINTN P7Size, + IN CONST UINT8 *TrustedCert, + IN UINTN CertSize, + IN OUT UINT8 **Data, + IN OUT UINTN *DataSize + ); + +EFI_STATUS +PeiVerifySig +( + IN CONST AMI_CRYPT_DIGITAL_SIGNATURE_PPI *This, + IN PEI_CRYPT_HANDLE *PublicKey, + IN PEI_CRYPT_HANDLE *Hash, + IN VOID *Signature, + IN UINTN SignatureSize, + IN UINT32 Flags +); + +EFI_STATUS +PeiGetKey +( + IN CONST AMI_CRYPT_DIGITAL_SIGNATURE_PPI *This, + IN CONST EFI_GUID *KeyAlgorithm, // reserved to PKPUB_KEY_GUID + IN PEI_CRYPT_HANDLE *PublicKey + ); + +EFI_STATUS +PeiVerifyKey +( + IN CONST AMI_CRYPT_DIGITAL_SIGNATURE_PPI *This, + IN CONST EFI_GUID *KeyAlgorithm, // reserved to PKPUB_KEY_GUID + IN PEI_CRYPT_HANDLE *PublicKey + ); + +//---------------------------------------------------------------------------- +// Crypto Protocol Identifiers +//---------------------------------------------------------------------------- +static EFI_GUID gAmiDigitalSignaturePPIGuid = AMI_DIGITAL_SIGNATURE_PPI_GUID; + +AMI_CRYPT_DIGITAL_SIGNATURE_PPI mSigPeiInitPpi = { + PeiHash, + PeiVerifyKey, + PeiVerifySig, + PeiGetKey, + PeiPkcs7Verify +}; + +//static +EFI_PEI_PPI_DESCRIPTOR mPpiSigListVariable = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gAmiDigitalSignaturePPIGuid, + &mSigPeiInitPpi +}; + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: CryptoGetRawImage +// +// Description: Loads binary from RAW section of X firwmare volume +// +// +// Output: Buffer - returns a pointer to allocated memory. Caller +// must free it when done. +// Size - returns the size of the binary loaded into the +// buffer. +// +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS +CryptoGetRawImage (IN EFI_GUID *FileGuid, IN OUT VOID **Buffer, IN OUT UINTN *Size) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER *pFV; + UINTN FvNum=0; + EFI_FFS_FILE_HEADER *ppFile=NULL; + + if (!Buffer || !Size) + return EFI_INVALID_PARAMETER; + + Status = (*gPeiServices)->FfsFindNextVolume (gPeiServices, FvNum, &pFV); + + while(TRUE) + { + Status = (*gPeiServices)->FfsFindNextFile(gPeiServices, EFI_FV_FILETYPE_ALL, pFV, &ppFile); + if(Status == EFI_NOT_FOUND) + { +// FvNum++; +// Status = (*gPeiServices)->FfsFindNextVolume (gPeiServices, FvNum, &pFV); +// if(EFI_ERROR(Status)) return Status; +// continue; +// !!! the PK Key may only be in FV_BB volume. FvNum=0!!!! + return Status; + } + + if(guidcmp(&ppFile->Name, FileGuid)==0) break; + } + + // hopefully we found the file...now try to read raw data + // !!! Keys are uncompressed. There is no much reason to run compression on prime numbers anyway + Status = (*gPeiServices)->FfsFindSectionData(gPeiServices, EFI_SECTION_RAW, ppFile, Buffer); + if(!EFI_ERROR(Status)) { + // Size may need to subtract Section hdr size = 28 bytes sizeof(EFI_FFS_FILE_HEADER + EFI_COMMON_SECTION_HEADER) + *Size = FVFILE_SIZE(ppFile)-sizeof(EFI_FFS_FILE_HEADER)-sizeof(EFI_COMMON_SECTION_HEADER); + } +PEI_TRACE(((UINTN)TRACE_ALWAYS, gPeiServices, "Find Key Ffs %r addr=%X (%X,%X), size=%d\n", Status, (UINT32)*Buffer, ((UINT8*)*Buffer)[0], ((UINT8*)*Buffer)[1], *Size)); + + return Status; +} + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: PeiHash +// +// Description: Allows creating a hash of an arbitrary message digest using one or more hash algorithms +// +// Input: +// This Pointer to the AMI_CRYPT_DIGITAL_SIGNATURE_PPI instance. +// HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use. +// num_elem Number of blocks to be passed via next argument:addr[] +// addr[] Pointer to array of UINT8* addresses of data blocks to be hashed +// len Pointer to array of integers containing length of each block listed by addr[] +// Hash Holds the resulting hash computed from the message. +// +// Output: +// EFI_SUCCESS Hash returned successfully. +// EFI_INVALID_PARAMETER Message or Hash is NULL +// EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this +// driver. +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS +PeiHash ( + IN CONST AMI_CRYPT_DIGITAL_SIGNATURE_PPI *This, + IN CONST EFI_GUID *HashAlgorithm, + IN UINTN num_elem, + IN CONST UINT8 *addr[], + IN CONST UINTN *len, + OUT UINT8 *Hash + ) +{ + BOOLEAN bSha1 = FALSE, bSha256 = FALSE; + UINT32 HashLen=SHA256_DIGEST_SIZE; + +// Support only SHA1 & SHA256 hashes + if(!guidcmp((EFI_GUID*)HashAlgorithm, &gEfiHashAlgorithmSha1Guid)) + { + bSha1 = TRUE; + HashLen = SHA1_DIGEST_SIZE; + } + else + if(!guidcmp((EFI_GUID*)HashAlgorithm, &gEfiHashAlgorithmSha256Guid)) + { + bSha256 = TRUE; + HashLen = SHA256_DIGEST_SIZE; + } + else + return EFI_UNSUPPORTED; + + MemSet(Hash, HashLen, 0); + if(bSha1) + sha1_vector(num_elem, addr, len, Hash); + else + sha256_vector(num_elem, addr, len, Hash); + + + return EFI_SUCCESS; +} + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: PeiVerifySig +// +// Description: Function verifies that the specified signature matches the specified hash. +// This function decrypts the signature with the provided key and then compares +// the decrypted value to the specified hash value +// +// Input: +// This Pointer to the AMI_CRYPT_DIGITAL_SIGNATURE_PPI instance. +// PublicKey Handle to a key used for verifying signatures. This handle must be identifying a public key. +// Hash Handle of the hash object to verify. +// Signature Pointer to the signature data to be verified. +// SignatureSize The size, in bytes, of the signature data. +// Flags Specifies additional flags to further customize the signing/verifying behavior. +// +// Output: +// EFI_SUCCESS The signature is successfully verified. +// EFI_SECURITY_VIOLATION The signature does not match the given message. +// EFI_ACCESS_DENIED The key could not be used in signature operation. +// EFI_INVALID_PARAMETER The size of input message or signature does not meet the criteria +// of the underlying signature algorithm. +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS +PeiVerifySig +( + IN CONST AMI_CRYPT_DIGITAL_SIGNATURE_PPI *This, + IN PEI_CRYPT_HANDLE *PublicKey, + IN PEI_CRYPT_HANDLE *Hash, + IN VOID *Signature, + IN UINTN SignatureSize, + IN UINT32 Flags + ) +{ + EFI_STATUS Status; + INTN err; + struct crypto_rsa_key *key = NULL; + UINT16 Size = (UINT16)(PublicKey->BlobSize); + size_t *sig_len=(size_t*)&SignatureSize; + INT32 modulus_bitlen = DEFAULT_RSA_SIG_LEN << 3; + UINT32 HashLen; + +// Only supporting RSASSA_PKCS1V15 signature types + if(!((Flags & EFI_CRYPT_RSASSA_PKCS1V15) || + (Flags & EFI_CRYPT_RSASSA_PSS)) ) + return EFI_INVALID_PARAMETER; + + ResetCRmm(); + +// check Key handle if requested PubKey is a Platform FW Key +// In this case use the FW key from ffs image +// validity of the Key must be verified prior to calling VerifySig +// Guid must match one of the valid keys we can use in PEI Sig verification. +// For now Public Key is supported in 2 formats: RAW 256 bytes and ASN.1 Integer +// shall be extended to gPBkey_x509_Guid + if(!guidcmp(&PublicKey->AlgGuid, &gEfiCertRsa2048Guid)) + key = crypto_import_rsa2048_public_key(PublicKey->Blob, Size, (UINT8*)&KeyE, LenE); + else + return EFI_INVALID_PARAMETER; + + if(!guidcmp(&Hash->AlgGuid, &gEfiHashAlgorithmSha256Guid)) + HashLen = SHA256_DIGEST_SIZE; + else if(!guidcmp(&Hash->AlgGuid, &gEfiHashAlgorithmSha1Guid)) + HashLen = SHA1_DIGEST_SIZE; + else + HashLen = SHA256_DIGEST_SIZE; + + if(key == NULL ) + err = -1; + else + err = crypto_rsa_exptmod((const UINT8*)Signature, (size_t)SignatureSize, (UINT8*)&DecriptedSig, sig_len, key, 0); +// locate Hash inside the decrypted signature body and compare it with given Hash; +// Should be extended to handle sha1, sha256 hashes. use Hash->AlgGuid to determine the Hash type + if(!err) + { + if(Flags & EFI_CRYPT_RSASSA_PKCS1V15) + { + // Validate PKCS#1v1.5 Padding +// err = pkcs_1_v1_5_decode(Hash->Blob, HashLen, (const UINT8 *)&DecriptedSig, (unsigned long)*sig_len); +// just compare the hash at the end of the sig blob + err = MemCmp(Hash->Blob, (void*)((UINT32)DecriptedSig + (UINT32)(*sig_len - HashLen)), HashLen); + } else //(Flags & EFI_CRYPT_RSASSA_PSS)) + // Validate PKCS#1 PSS Signature: padding & hash + err = pkcs_1_pss_decode( + Hash->Blob, HashLen, + (const unsigned char *)&DecriptedSig, (unsigned long)*sig_len, + saltlen, modulus_bitlen); + } + + Status = !err ? EFI_SUCCESS:EFI_SECURITY_VIOLATION; + +// Security concern, memory heap is being cleared on exit + ResetCRmm(); + + return Status; +} + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: PeiPkcs7Verify +// +// Description: Verifies the validity of a PKCS#7 signed data as described in "PKCS #7: Cryptographic +// Message Syntax Standard". +// Function verifies validity of the signature contained inside the Certificate +// This function decrypts the signature with the Public key from the Signer certificate +// and then compares the decrypted value to the input Data +// +// Input: +// This Pointer to the AMI_CRYPT_DIGITAL_SIGNATURE_PPI instance. +// P7Data Pointer to the PKCS#7 DER encoded message to verify. +// P7Size Size of the PKCS#7 message in bytes. +// TrustedCert Pointer to a trusted/root X509 certificate encoded in DER, which +// is used for certificate chain verification. +// CertSize Size of the trusted certificate in bytes. +// Data Pointer to the content to be verified/returned at +// DataSize Size of Data in bytes +// +// Output: +// EFI_SUCCESS The specified PKCS#7 signed data is valid +// EFI_SECURITY_VIOLATION Invalid PKCS#7 signed data. +// EFI_ACCESS_DENIED The Trusted certificate does not have a match in SignedData.certificate store. +// EFI_INVALID_PARAMETER The size of input message or signature does not meet the criteria +// of the underlying signature algorithm. +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS +PeiPkcs7Verify ( + IN CONST AMI_CRYPT_DIGITAL_SIGNATURE_PPI *This, + IN CONST UINT8 *P7Data, + IN UINTN P7Size, + IN CONST UINT8 *TrustedCert, + IN UINTN CertSize, + IN OUT UINT8 **Data, + IN OUT UINTN *DataSize + ) +{ +#if CONFIG_PEI_PKCS7 == 1 + + EFI_STATUS Status; + INTN err, reason; + struct pkcs7_signed_data_st* PKCS7cert; + struct x509_certificate *x509TrustCert; + struct x509_certificate *x509SignCert; + + err = -1; + reason = 0; + x509SignCert = NULL; + + if((*Data == NULL || DataSize == NULL) || + (!P7Data || P7Size== 0) || + (!TrustedCert || CertSize== 0) + ) + return EFI_INVALID_PARAMETER; + + ResetCRmm(); + + PKCS7cert = Pkcs7_parse_Authenticode_certificate(P7Data, P7Size); + if (PKCS7cert) { + // verify Pkcs7 Signing Cert chain up to the TrustCert... + x509TrustCert = x509_certificate_parse(TrustedCert, CertSize); + if(x509TrustCert) { + err = Pkcs7_x509_certificate_chain_validate(PKCS7cert, x509TrustCert, (int*)&reason); + if(!err) + err = Pkcs7_certificate_validate_digest(PKCS7cert, x509SignCert, *Data, *DataSize); + } + } + + // Security concern, memory heap is being cleared on exit + ResetCRmm(); + + // failed to process + Status = !err ? EFI_SUCCESS:EFI_SECURITY_VIOLATION; + + return Status; +#else + return EFI_UNSUPPORTED; +#endif +} + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: PeiGetKey +// +// Description: Function returns Ptr to a Platform Signing Key (PK) Ffs +// inside Recovery FV (FV_BB or similar) +// +// Input: +// This Pointer to the AMI_CRYPT_DIGITAL_SIGNATURE_PPI instance. +// KeyAlgorithm Points to the EFI_GUID which identifies the PKpub algorithm to use. +// PublicKey Handle to a key used to return a ptr to a Key. This handle must be identifying a public key. +// +// Output: +// EFI_SUCCESS The Key is successfully returned. +// EFI_NOT_FOUND The Key not found +// EFI_ACCESS_DENIED The key could not be used in signature operation. +// EFI_INVALID_PARAMETER The size of input message or signature does not meet the criteria +// of the underlying signature algorithm. +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS +PeiGetKey ( + IN CONST AMI_CRYPT_DIGITAL_SIGNATURE_PPI *This, + IN CONST EFI_GUID *KeyAlgorithm, // reserved to PKPUB_KEY_GUID + IN PEI_CRYPT_HANDLE *PublicKey + ) +{ + if(!PublicKey || !KeyAlgorithm) + return EFI_INVALID_PARAMETER; + + // now only supporting PKpub key comparison + if(guidcmp((EFI_GUID*)KeyAlgorithm, &gPKeyGuid)) + return EFI_INVALID_PARAMETER; + + if(pFwKeyHob) { + PublicKey->AlgGuid = pFwKeyHob->KeyGuid; + PublicKey->Blob = (UINT8*)pFwKeyHob->KeyAddress; + PublicKey->BlobSize = pFwKeyHob->KeySize; + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: PeiVerifyKey +// +// Description: Function compares the input PublicKey against +// Platform Signing Key (PK) image in the flash. +// +// Input: +// This Pointer to the AMI_CRYPT_DIGITAL_SIGNATURE_PPI instance. +// KeyAlgorithm Points to the EFI_GUID which identifies the PKpub algorithm to use. +// PublicKey Handle to a key used for verifying signatures. This handle must be identifying a public key. +// +// Output: +// EFI_SUCCESS The Key is successfully verified. +// EFI_SECURITY_VIOLATION The Key does not match current FW key. +// EFI_ACCESS_DENIED The key could not be used in signature operation. +// EFI_INVALID_PARAMETER The size of input message or signature does not meet the criteria +// of the underlying signature algorithm. +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS +PeiVerifyKey +( + IN CONST AMI_CRYPT_DIGITAL_SIGNATURE_PPI *This, + IN CONST EFI_GUID *KeyAlgorithm, // reserved to PKPUB_KEY_GUID + IN PEI_CRYPT_HANDLE *PublicKey + ) +{ + EFI_STATUS Status; + int err; + PEI_CRYPT_HANDLE KeyHndl; + UINT8 Hash[SHA256_DIGEST_SIZE] = {0}; + UINT8 *KeyBuf, *PKpubBuffer=NULL; + UINT32 KeyLen; + + if(!PublicKey || !KeyAlgorithm || !PublicKey->Blob) + return EFI_INVALID_PARAMETER; +// check Key handle if requested PubKey is a Platform Key PKpub. +// In this case use PKpub key from ffs image + if(guidcmp((EFI_GUID*)KeyAlgorithm, &gPKeyGuid)) + return EFI_INVALID_PARAMETER; + + Status = PeiGetKey(This, KeyAlgorithm, &KeyHndl); + if(!EFI_ERROR(Status)) { +// only store Sha256 or n-modulus of RSA2048. For x509 cert - compare hash of an entire cert +// FFS - Sha256 Hash -> +// Input =Sha258 -> cmp +// Input =RSA2048 -> Hash n-modulus +// Input =x509 -> Hash x509 cert +// FFS - RSA2048 -> +// Input =RSA2048 -> cmp +// Input =x509 -> extract n-modulus +// FFS - x5098 -> +// Input =x509 -> cmp +/* + PKpubBuffer = KeyHndl.Blob; + KeyLen = KeyHndl.BlobSize; // always 256 + KeyBuf = PublicKey->Blob; + + if(!guidcmp(&KeyHndl.AlgGuid, &gEfiCertSha256Guid)) { + KeyBuf = Hash; + KeyLen = SHA256_DIGEST_SIZE; + if(!guidcmp(&PublicKey->AlgGuid, &gEfiCertRsa2048Guid) || + !guidcmp(&PublicKey->AlgGuid, &gEfiCertX509Guid) ) { + // SHA256 Hash of RSA Key/x509 cert + sha256_vector(1, (const UINT8**)&PublicKey->Blob, (const UINTN*)&PublicKey->BlobSize, Hash); + } + } else + // if FwKey is x509 and Key->Algo - gEfiCertRsa2048Guid: + // derive nModulus from x509 Key Cert for comparison + if(!guidcmp(&KeyHndl.AlgGuid, &gEfiCertRsa2048Guid) && + !guidcmp(&PublicKey->AlgGuid, &gEfiCertX509Guid) ) { + PKpubBuffer = &Hash[0]; + KeyLen = DEFAULT_RSA_KEY_MODULUS_LEN; + ResetCRmm(); + err = Pkcs7_x509_return_Cert_pubKey((UINT8*)PublicKey->Blob, (UINTN)PublicKey->BlobSize, &PKpubBuffer, &KeyLen); + ResetCRmm(); + if(err) return EFI_SECURITY_VIOLATION; + } +*/ + PKpubBuffer = KeyHndl.Blob; + KeyLen = KeyHndl.BlobSize; // always 256 + KeyBuf = PublicKey->Blob; + if(!guidcmp(&KeyHndl.AlgGuid, &gEfiCertSha256Guid) && + !guidcmp(&PublicKey->AlgGuid, &gEfiCertRsa2048Guid) + ) { + // SHA256 Hash of RSA Key + KeyLen = SHA256_DIGEST_SIZE; + KeyBuf = Hash; + sha256_vector(1, (const UINT8**)&PublicKey->Blob, (const UINTN*)&PublicKey->BlobSize, KeyBuf); +#if CONFIG_PEI_PKCS7 == 1 + } else { + // if FwKey is x509 and Key->Algo - gEfiCertRsa2048Guid: + // derive nModulus from x509 Key Cert for comparison + if(!guidcmp(&KeyHndl.AlgGuid, &gEfiCertRsa2048Guid) && + !guidcmp(&PublicKey->AlgGuid, &gEfiCertX509Guid) + ) { + PKpubBuffer = &Hash[0]; + KeyLen = DEFAULT_RSA_KEY_MODULUS_LEN; + ResetCRmm(); + err = Pkcs7_x509_return_Cert_pubKey((UINT8*)PublicKey->Blob, (UINTN)PublicKey->BlobSize, &PKpubBuffer, &KeyLen); + ResetCRmm(); + if(err) return EFI_SECURITY_VIOLATION; + } +#endif + } + + err = MemCmp(PKpubBuffer, KeyBuf, KeyLen); + Status = !err ? EFI_SUCCESS:EFI_SECURITY_VIOLATION; + + } + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CryptoPei_Init +// +// Description: This function is the entry point for this PEI. +// +// +// Input: FfsHeader Pointer to the FFS file header +// PeiServices Pointer to the PEI services table +// +// Output: Return Status based on errors that occurred while waiting for +// time to expire. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +CryptoPei_Init ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + EFI_STATUS Status; + UINTN Size; + UINTN Npages; + EFI_PHYSICAL_ADDRESS DstAddress; + EFI_BOOT_MODE BootMode; + UINT8 Index; + UINT8 *pBuf; + + gPeiServices = PeiServices; + + Status = (*gPeiServices)->GetBootMode( PeiServices, &BootMode ); + if(EFI_ERROR(Status) || BootMode == BOOT_ON_S3_RESUME) { + return Status; // skip Crypto PPI install on S3 resume + } + +//////////////////////////////////////////////////////////////////////////////////// +// +// Create FwKey Hob +// +//////////////////////////////////////////////////////////////////////////////////// + Index = 0; + while(gKeyFileGuid[Index] != NULL) + { +// Available Key Cert GUIDs: RSA2048, SHA256 and x509 + Status = CryptoGetRawImage(gKeyFileGuid[Index], (VOID**)&pBuf, (UINTN*)&Size); + if(!EFI_ERROR(Status)) { + // make sure the Key buffer is mapped to FV_BB address space +/* + if(!((UINT32)pBuf > FV_BB_BASE && + (UINT64)((UINT32)pBuf+Size) < + (UINT64)(FV_BB_BASE+(UINT64)FV_BB_BLOCKS*FLASH_BLOCK_SIZE))) + break; +*/ + Status = (*PeiServices)->CreateHob( + PeiServices, EFI_HOB_TYPE_GUID_EXTENSION, + sizeof(FW_KEY_HOB), &pFwKeyHob); + if (!EFI_ERROR(Status) && pFwKeyHob) { + pFwKeyHob->Header.Name = gPKeyGuid; + pFwKeyHob->KeyGuid = *gKeyTypeGuid[Index]; + pFwKeyHob->KeyAddress = (EFI_PHYSICAL_ADDRESS)(UINT32)pBuf; + pFwKeyHob->KeySize = Size; + } + break; + } + Index++; + } + +//////////////////////////////////////////////////////////////////////////////////// +// +// Init Aux Memory Manager +// +//////////////////////////////////////////////////////////////////////////////////// +// convert the Heap Size in bytes to the number of pages and allocate appropriate number of pages + + Size = CR_PEI_MAX_HEAP_SIZE; + Npages = EFI_SIZE_TO_PAGES(Size); + Status = (*gPeiServices)->AllocatePages(gPeiServices, EfiBootServicesData, Npages, &DstAddress); + PEI_TRACE(((UINTN)TRACE_ALWAYS, gPeiServices, "Heap alloc %r (addr=%X, size=%d)\n", Status, (UINT32)DstAddress, Size)); + if(EFI_ERROR(Status)) + { + return Status; + } + InitCRmm((void*)DstAddress, Size); + // + // Update Crypto debug traces level + // + wpa_set_trace_level(CRYPTO_trace_level); + +//////////////////////////////////////////////////////////////////////////////////// +// +// Install VerifySig PPI +// +//////////////////////////////////////////////////////////////////////////////////// + return (**gPeiServices).InstallPpi (gPeiServices, &mPpiSigListVariable); +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/CryptoPkg/CryptoPei.dxs b/Core/EM/CryptoPkg/CryptoPei.dxs new file mode 100644 index 0000000..86c2008 --- /dev/null +++ b/Core/EM/CryptoPkg/CryptoPei.dxs @@ -0,0 +1,54 @@ +//**************************************************************************** +//**************************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone (770)-246-8600 ** +//** ** +//**************************************************************************** +//**************************************************************************** +//********************************************************************** +// $Header: /Alaska/BIN/Modules/CryptoPkg/CryptoPei.dxs 1 6/13/11 5:19p Alexp $ +// +// $Revision: 1 $ +// +// $Date: 6/13/11 5:19p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/BIN/Modules/CryptoPkg/CryptoPei.dxs $ +// +// 1 6/13/11 5:19p Alexp +// +// 1 5/06/11 6:11p Alexp +// initial module release +// +// 1 3/10/11 4:52p Alexp +// +// 1 2/18/11 5:42p Alexp +// +//********************************************************************** +#include <pei.h> +//#include <Ppi\ReadOnlyVariable.h> +#include <token.h> + +DEPENDENCY_START + EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI +DEPENDENCY_END +//**************************************************************************** +//**************************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone (770)-246-8600 ** +//** ** +//**************************************************************************** +//**************************************************************************** diff --git a/Core/EM/CryptoPkg/CryptoPkg.cif b/Core/EM/CryptoPkg/CryptoPkg.cif new file mode 100644 index 0000000..9a35890 --- /dev/null +++ b/Core/EM/CryptoPkg/CryptoPkg.cif @@ -0,0 +1,9 @@ +<component> + name = "CryptoPkg" + category = eModule + LocalRoot = "Core\EM\CryptoPkg\" + RefName = "CryptoPkg" +[parts] +"CryptoAPI" +"CryptoLIB" +<endComponent> |