From: Long, Qin Date: Thu, 25 Dec 2014 08:37:08 +0000 (+0000) Subject: Correct the Hash Calculation for Revoked X.509 Certificate to align with RFC3280... X-Git-Tag: edk2-stable201903~10500 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=12d95665cb0e088afe2cd395f0acc7fdb2604acc Correct the Hash Calculation for Revoked X.509 Certificate to align with RFC3280 and UEFI 2.4 Spec. This patch added one new X509GetTBSCert() interface in BaseCryptLib to retrieve the TBSCertificate, and also corrected the hash calculation for revoked certificate to aligned the RFC3280 and UEFI 2.4 spec. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: "Long, Qin" Reviewed-by: "Dong, Guo" git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16559 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h index e36041bf4f..bc36ac7fd1 100644 --- a/CryptoPkg/Include/Library/BaseCryptLib.h +++ b/CryptoPkg/Include/Library/BaseCryptLib.h @@ -1906,6 +1906,32 @@ X509StackFree ( IN VOID *X509Stack ); +/** + Retrieve the TBSCertificate from one given X.509 certificate. + + @param[in] Cert Pointer to the given DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] TBSCert DER-Encoded To-Be-Signed certificate. + @param[out] TBSCertSize Size of the TBS certificate in bytes. + + If Cert is NULL, then return FALSE. + If TBSCert is NULL, then return FALSE. + If TBSCertSize is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @retval TRUE The TBSCertificate was retrieved successfully. + @retval FALSE Invalid X.509 certificate. + +**/ +BOOLEAN +EFIAPI +X509GetTBSCert ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 **TBSCert, + OUT UINTN *TBSCertSize + ); + /** Get the signer's certificates from PKCS#7 signed data as described in "PKCS #7: Cryptographic Message Syntax Standard". The input signed data could be wrapped @@ -2067,6 +2093,7 @@ AuthenticodeVerify ( signature. If AuthData is NULL, then return FALSE. + If this interface is not supported, then return FALSE. @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed PE/COFF image to be verified. diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c index 5abe970cce..29efc42b02 100644 --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c @@ -1,7 +1,7 @@ /** @file X.509 Certificate Handler Wrapper Implementation over OpenSSL. -Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.
+Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -484,3 +484,79 @@ _Exit: return Status; } + +/** + Retrieve the TBSCertificate from one given X.509 certificate. + + @param[in] Cert Pointer to the given DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] TBSCert DER-Encoded To-Be-Signed certificate. + @param[out] TBSCertSize Size of the TBS certificate in bytes. + + If Cert is NULL, then return FALSE. + If TBSCert is NULL, then return FALSE. + If TBSCertSize is NULL, then return FALSE. + + @retval TRUE The TBSCertificate was retrieved successfully. + @retval FALSE Invalid X.509 certificate. + +**/ +BOOLEAN +EFIAPI +X509GetTBSCert ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 **TBSCert, + OUT UINTN *TBSCertSize + ) +{ + CONST UINT8 *Temp; + INTN Asn1Tag; + INTN ObjClass; + UINTN Length; + + // + // Check input parameters. + // + if ((Cert == NULL) || (TBSCert == NULL) || (TBSCertSize == NULL)) { + return FALSE; + } + + // + // An X.509 Certificate is: (defined in RFC3280) + // Certificate ::= SEQUENCE { + // tbsCertificate TBSCertificate, + // signatureAlgorithm AlgorithmIdentifier, + // signature BIT STRING } + // + // and + // + // TBSCertificate ::= SEQUENCE { + // version [0] Version DEFAULT v1, + // ... + // } + // + // So we can just ASN1-parse the x.509 DER-encoded data. If we strip + // the first SEQUENCE, the second SEQUENCE is the TBSCertificate. + // + Temp = Cert; + ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)CertSize); + + if (Asn1Tag != V_ASN1_SEQUENCE) { + return FALSE; + } + + *TBSCert = (UINT8 *)Temp; + + ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)Length); + // + // Verify the parsed TBSCertificate is one correct SEQUENCE data. + // + if (Asn1Tag != V_ASN1_SEQUENCE) { + return FALSE; + } + + *TBSCertSize = Length + (Temp - *TBSCert); + + return TRUE; +} diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c index 5dbddca423..e1eb84d99b 100644 --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c @@ -2,7 +2,7 @@ X.509 Certificate Handler Wrapper Implementation which does not provide real capabilities. -Copyright (c) 2012, Intel Corporation. All rights reserved.
+Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -178,3 +178,29 @@ X509VerifyCert ( ASSERT (FALSE); return FALSE; } + +/** + Retrieve the TBSCertificate from one given X.509 certificate. + + Return FALSE to indicate this interface is not supported. + + @param[in] Cert Pointer to the given DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] TBSCert DER-Encoded To-Be-Signed certificate. + @param[out] TBSCertSize Size of the TBS certificate in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +X509GetTBSCert ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 **TBSCert, + OUT UINTN *TBSCertSize + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibRuntimeCryptProtocol/Pk/CryptX509Null.c b/CryptoPkg/Library/BaseCryptLibRuntimeCryptProtocol/Pk/CryptX509Null.c index 5dbddca423..c43ca07583 100644 --- a/CryptoPkg/Library/BaseCryptLibRuntimeCryptProtocol/Pk/CryptX509Null.c +++ b/CryptoPkg/Library/BaseCryptLibRuntimeCryptProtocol/Pk/CryptX509Null.c @@ -2,7 +2,7 @@ X.509 Certificate Handler Wrapper Implementation which does not provide real capabilities. -Copyright (c) 2012, Intel Corporation. All rights reserved.
+Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -178,3 +178,29 @@ X509VerifyCert ( ASSERT (FALSE); return FALSE; } + +/** + Retrieve the TBSCertificate from one given X.509 certificate. + + Return FALSE to indicate this interface is not supported. + + @param[in] Cert Pointer to the given DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] TBSCert DER-Encoded To-Be-Signed certificate. + @param[out] TBSCertSize Size of the TBS certificate in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +X509GetTBSCert ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 **TBSCert, + OUT UINTN *TBSCertSize + ) +{ + ASSERT (FALSE); + return FALSE; +} \ No newline at end of file diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c index 2475f35c85..959a9b062d 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c @@ -852,6 +852,8 @@ IsCertHashFoundInDatabase ( UINT8 CertDigest[MAX_DIGEST_SIZE]; UINT8 *DbxCertHash; UINTN SiglistHeaderSize; + UINT8 *TBSCert; + UINTN TBSCertSize; IsFound = FALSE; DbxList = SignatureList; @@ -859,8 +861,16 @@ IsCertHashFoundInDatabase ( HashCtx = NULL; HashAlg = HASHALG_MAX; - ASSERT (RevocationTime != NULL); - ASSERT (DbxList != NULL); + if ((RevocationTime == NULL) || (DbxList == NULL)) { + return FALSE; + } + + // + // Retrieve the TBSCertificate from the X.509 Certificate. + // + if (!X509GetTBSCert (Certificate, CertSize, &TBSCert, &TBSCertSize)) { + return FALSE; + } while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) { // @@ -879,7 +889,7 @@ IsCertHashFoundInDatabase ( } // - // Calculate the hash value of current db certificate for comparision. + // Calculate the hash value of current TBSCertificate for comparision. // if (mHash[HashAlg].GetContextSize == NULL) { goto Done; @@ -893,7 +903,7 @@ IsCertHashFoundInDatabase ( if (!Status) { goto Done; } - Status = mHash[HashAlg].HashUpdate (HashCtx, Certificate, CertSize); + Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize); if (!Status) { goto Done; } diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c index 517d9d9904..5b8ae7e8d8 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c @@ -1073,6 +1073,8 @@ CalculateCertHash ( BOOLEAN Status; VOID *HashCtx; UINTN CtxSize; + UINT8 *TBSCert; + UINTN TBSCertSize; HashCtx = NULL; Status = FALSE; @@ -1081,6 +1083,13 @@ CalculateCertHash ( return FALSE; } + // + // Retrieve the TBSCertificate for Hash Calculation. + // + if (!X509GetTBSCert (CertData, CertSize, &TBSCert, &TBSCertSize)) { + return FALSE; + } + // // 1. Initialize context of hash. // @@ -1099,7 +1108,7 @@ CalculateCertHash ( // // 3. Calculate the hash. // - Status = mHash[HashAlg].HashUpdate (HashCtx, CertData, CertSize); + Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize); if (!Status) { goto Done; }