2024-03-13 03:50:21 +01:00
|
|
|
/** @file
|
|
|
|
RFC3161 Timestamp Countersignature Verification Wrapper Implementation which does
|
|
|
|
not provide real capabilities.
|
|
|
|
|
|
|
|
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include "InternalCryptLib.h"
|
|
|
|
#include <mbedtls/asn1.h>
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
)
|
|
|
|
{
|
2024-08-29 19:44:18 +02:00
|
|
|
UINT8 *Ptr;
|
|
|
|
UINT8 *End;
|
|
|
|
INT32 Len;
|
|
|
|
UINTN ObjLen;
|
|
|
|
UINT8 *TempPtr;
|
2024-03-13 03:50:21 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// 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);
|
2024-08-29 19:44:18 +02:00
|
|
|
return ConvertAsn1TimeToEfiTime (Ptr, SigningTime);
|
2024-03-13 03:50:21 +01:00
|
|
|
}
|
|
|
|
|
2024-08-29 19:44:18 +02:00
|
|
|
return TRUE;
|
2024-03-13 03:50:21 +01:00
|
|
|
}
|