/** @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; }