From 3096fcf81da082219b3db5e990f3a14aa55d45cc Mon Sep 17 00:00:00 2001 From: Wenxing Hou Date: Wed, 13 Mar 2024 10:50:21 +0800 Subject: CryptoPkg: Add ImageTimestampVerify based on Mbedtls REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4177 Timestamp Countersignature Verification implementaion based on Mbedtls. Cc: Jiewen Yao Cc: Yi Li Signed-off-by: Wenxing Hou Reviewed-by: Yi Li Acked-by: Jiewen Yao --- CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c | 381 +++++++++++++++++++++ 1 file changed, 381 insertions(+) create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c (limited to 'CryptoPkg') diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c new file mode 100644 index 0000000000..d3fa205f9c --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c @@ -0,0 +1,381 @@ +/** @file + RFC3161 Timestamp Countersignature Verification Wrapper Implementation which does + not provide real capabilities. + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#include + +// +// OID ASN.1 Value for SPC_RFC3161_OBJID ("1.3.6.1.4.1.311.3.3.1") +// +GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mSpcRFC3161OidValue[] = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x03, 0x03, 0x01 +}; + +/** + Convert ASN.1 GeneralizedTime to EFI Time. + + @param[in] Ptr Pointer to the ASN.1 GeneralizedTime to be converted. + @param[out] EfiTime Return the corresponding EFI Time. + + @retval TRUE The time conversion succeeds. + @retval FALSE Invalid parameters. + +**/ +STATIC +BOOLEAN +ConvertAsn1TimeToEfiTime ( + IN UINT8 *Ptr, + OUT EFI_TIME *EfiTime + ) +{ + CONST CHAR8 *Str; + UINTN Index; + + if ((Ptr == NULL) || (EfiTime == NULL)) { + return FALSE; + } + + Str = (CONST CHAR8 *)Ptr; + SetMem (EfiTime, sizeof (EFI_TIME), 0); + + Index = 0; + + /* four digit year */ + EfiTime->Year = (Str[Index++] - '0') * 1000; + EfiTime->Year += (Str[Index++] - '0') * 100; + EfiTime->Year += (Str[Index++] - '0') * 10; + EfiTime->Year += (Str[Index++] - '0'); + if ((EfiTime->Year < 1900) || (EfiTime->Year > 9999)) { + return FALSE; + } + + EfiTime->Month = (Str[Index++] - '0') * 10; + EfiTime->Month += (Str[Index++] - '0'); + if ((EfiTime->Month < 1) || (EfiTime->Month > 12)) { + return FALSE; + } + + EfiTime->Day = (Str[Index++] - '0') * 10; + EfiTime->Day += (Str[Index++] - '0'); + if ((EfiTime->Day < 1) || (EfiTime->Day > 31)) { + return FALSE; + } + + EfiTime->Hour = (Str[Index++] - '0') * 10; + EfiTime->Hour += (Str[Index++] - '0'); + if (EfiTime->Hour > 23) { + return FALSE; + } + + EfiTime->Minute = (Str[Index++] - '0') * 10; + EfiTime->Minute += (Str[Index++] - '0'); + if (EfiTime->Minute > 59) { + return FALSE; + } + + EfiTime->Second = (Str[Index++] - '0') * 10; + EfiTime->Second += (Str[Index++] - '0'); + if (EfiTime->Second > 59) { + return FALSE; + } + + /* Note: we did not adjust the time based on time zone information */ + + return TRUE; +} + +/** + Verifies the validity of a RFC3161 Timestamp CounterSignature embedded in PE/COFF Authenticode + signature. + + Return FALSE to indicate this interface is not supported. + + @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed + PE/COFF image to be verified. + @param[in] DataSize Size of the Authenticode Signature in bytes. + @param[in] TsaCert Pointer to a trusted/root TSA certificate encoded in DER, which + is used for TSA certificate chain verification. + @param[in] CertSize Size of the trusted certificate in bytes. + @param[out] SigningTime Return the time of timestamp generation time if the timestamp + signature is valid. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +ImageTimestampVerify ( + IN CONST UINT8 *AuthData, + IN UINTN DataSize, + IN CONST UINT8 *TsaCert, + IN UINTN CertSize, + OUT EFI_TIME *SigningTime + ) +{ + BOOLEAN Status; + UINT8 *Ptr; + UINT8 *End; + INT32 Len; + UINTN ObjLen; + UINT8 *TempPtr; + + // + // Initializations + // + if (SigningTime != NULL) { + SetMem (SigningTime, sizeof (EFI_TIME), 0); + } + + // + // Input Parameters Checking. + // + if ((AuthData == NULL) || (TsaCert == NULL)) { + return FALSE; + } + + if ((DataSize > INT_MAX) || (CertSize > INT_MAX)) { + return FALSE; + } + + Ptr = (UINT8 *)(UINTN)AuthData; + Len = (UINT32)DataSize; + End = Ptr + Len; + + // ContentInfo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // ContentType + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // content + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { + return FALSE; + } + + End = Ptr + ObjLen; + // signedData + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // version + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // digestAlgo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // encapContentInfo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // cert + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + TempPtr = Ptr; + // OPTIONAL CRLs + if (mbedtls_asn1_get_tag (&TempPtr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) { + Ptr = TempPtr + ObjLen; + } + + // signerInfo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) { + return FALSE; + } + + // sub parse + // signerInfo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + End = Ptr + ObjLen; + + // version + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // sid + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // digestalgo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // OPTIONAL AuthenticatedAttributes + TempPtr = Ptr; + if (mbedtls_asn1_get_tag (&TempPtr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) { + Ptr = TempPtr + ObjLen; + } + + // signaturealgo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // signature + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // OPTIONAL UnauthenticatedAttributes + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, 0xA1) != 0) { + return FALSE; + } + + // Attribute + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // type + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) { + return FALSE; + } + + if (CompareMem (Ptr, mSpcRFC3161OidValue, sizeof (mSpcRFC3161OidValue)) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // values + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) { + return FALSE; + } + + // values + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // signedData OID + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // [0] + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { + return FALSE; + } + + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // integer + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // SET + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // tST OID + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { + return FALSE; + } + + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return FALSE; + } + + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // Integer + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // policy OID + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // sequence + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // Integer + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // GeneralizedTime + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_GENERALIZED_TIME) != 0) { + return FALSE; + } + + // + // Retrieve the signing time from TS_TST_INFO structure. + // + if (SigningTime != NULL) { + SetMem (SigningTime, sizeof (EFI_TIME), 0); + Status = ConvertAsn1TimeToEfiTime (Ptr, SigningTime); + } + + return Status; +} -- cgit v1.2.3