Documentation ¶
Index ¶
- Variables
- func IsRegisteredType(sample any) bool
- func RegisterType(sample any)
- func SetValueCalculator[inputType, outputType any, T calculator[inputType, outputType]](dc *DataCalculator, calc T) error
- func TypeRegistry() xjson.TypeIDHandler
- type ActualBIOSInfo
- type ActualFirmware
- type ActualFirmwareBlob
- type ActualPCR0
- type ActualPSPFirmware
- type ActualRegisters
- type AlignedOriginalFirmware
- type Analyzer
- type AnalyzerID
- type AssetID
- type Blob
- type BytesBlob
- type CachedValue
- type DataCache
- type DataCalculator
- type DataCalculatorInterface
- type ErrAnalyze
- type ErrCalcNotSupported
- type ErrFailedCalcInput
- type ErrMissingInput
- type ErrNotApplicable
- type ErrResolveInput
- type ErrResolveValue
- type ErrTypeIDNotRegistered
- type FixedRegisters
- type Input
- func (in Input) AddActualBIOSInfo(biosInfo ActualBIOSInfo) Input
- func (in Input) AddActualFirmware(image Blob) Input
- func (in Input) AddActualPCR0(pcr []byte) Input
- func (in Input) AddActualRegisters(regs ActualRegisters) Input
- func (in Input) AddAssetID(assetID int64) Input
- func (in Input) AddCustomValue(v any) Input
- func (in Input) AddOriginalBIOSInfo(biosInfo OriginalBIOSInfo) Input
- func (in Input) AddOriginalFirmware(image Blob) Input
- func (in Input) AddTPMDevice(tpm tpmdetection.Type) Input
- func (in Input) AddTPMEventLog(eventLog *tpmeventlog.TPMEventLog) Input
- func (in Input) ForceBootFlow(_flow bootflowtypes.Flow) Input
- func (in Input) GoString() string
- func (in Input) MarshalJSON() ([]byte, error)
- func (in *Input) Scan(src any) error
- func (in *Input) UnmarshalJSON(b []byte) error
- func (in Input) Value() (driver.Value, error)
- type Issue
- type OriginalBIOSInfo
- type OriginalFirmware
- type OriginalFirmwareBlob
- type ReferenceFirmware
- type Report
- type Severity
- type TypeID
Constants ¶
This section is empty.
Variables ¶
var ( // AutoRegisterTypes automatically registers new types in the // type registry on an attempt to get TypeID of an unregistered // sample. AutoRegisterTypes = false )
Functions ¶
func IsRegisteredType ¶
IsRegisteredType returns true if the type of the provided sample is already registered (and could be used in analyzer input/output).
func RegisterType ¶
func RegisterType(sample any)
RegisterType registers the type of the provided sample into the registry. It allows to deserialize JSONs into typed values.
The sample may also be given as a (nil) pointer.
func SetValueCalculator ¶
func SetValueCalculator[inputType, outputType any, T calculator[inputType, outputType]](dc *DataCalculator, calc T) error
SetValueCalculator verifies and sets a function "calc" which can compute the values of parameters used as inputs for analyzers.
Note: There could be only one calculator for one output type. Setting a calculator for a type where a calculator is already set will overwrite the calculator.
TODO: The UNIQUE KEY for calculators should be not the outputType, but inputType+outputType. For example
BIOSInfo could be calculated from different input types and it should be allowed.
For example: firmware parsing, fixing register's values. Input argument should be a function of format func(ctx context.Context, in InputStruct) (Output1, Output2, ..., OutputN, []Issue, error)
func TypeRegistry ¶
func TypeRegistry() xjson.TypeIDHandler
TypeRegistry returns the TypeIDHandler for xjson package.
Types ¶
type ActualBIOSInfo ¶
ActualBIOSInfo represents data stored in the SMBIOS of the actual image.
func NewActualBIOSInfo ¶
func NewActualBIOSInfo(biosInfo dmidecode.BIOSInfo) *ActualBIOSInfo
NewActualBIOSInfo creates a new instance of ActualBIOSInfo
type ActualFirmware ¶
type ActualFirmware struct { Blob // contributes into cache key // contains filtered or unexported fields }
ActualFirmware represents parsed actual firmware (the one we dump)
func NewActualFirmware ¶
func NewActualFirmware(fw *uefi.UEFI, blob Blob) ActualFirmware
NewActualFirmware creates a new ActualFirmware object from firmware.
`blob` is optional, if not provided, then fw.Buf() is used instead.
func (ActualFirmware) UEFI ¶
func (of ActualFirmware) UEFI() *uefi.UEFI
UEFI returns an UEFI object of ActualFirmware
type ActualFirmwareBlob ¶
type ActualFirmwareBlob struct {
Blob
}
ActualFirmwareBlob represents raw bytes of the actual firmware image (the one obtained from the host)
func NewActualFirmwareBlob ¶
func NewActualFirmwareBlob(image Blob) ActualFirmwareBlob
NewActualFirmwareBlob creates a new ActualFirmwareBlob object
type ActualPSPFirmware ¶
type ActualPSPFirmware struct { Blob Blob // contributes to the cache key // contains filtered or unexported fields }
ActualPSPFirmware represents parsed original AMD PSP firmware (the one we get from the orig firmware table and expect to be installed on the host)
func NewActualPSPFirmware ¶
func NewActualPSPFirmware(amdFW *amd_manifest.AMDFirmware, blob Blob) ActualPSPFirmware
NewActualPSPFirmware creates a new ActualPSPFirmware object from firmware.
`blob` is optional, if not provided, then amdFW.Firmware().ImageBytes() is used instead.
func (ActualPSPFirmware) AMDFirmware ¶
func (af ActualPSPFirmware) AMDFirmware() *amd_manifest.AMDFirmware
AMDFirmware returns an AMDFirmware object
type ActualRegisters ¶
ActualRegisters represents the actual registers (the one obtained from the host)
func NewActualRegisters ¶
func NewActualRegisters(regs registers.Registers) (ActualRegisters, error)
NewActualRegisters creates new ActualRegisters object
func (ActualRegisters) CacheWrite ¶
func (ar ActualRegisters) CacheWrite(b *objhash.Builder) error
CacheWrite is an implementation of objhash.Custom interface
func (ActualRegisters) GetRegisters ¶
func (ar ActualRegisters) GetRegisters() registers.Registers
GetRegisters returns registers
type AlignedOriginalFirmware ¶
type AlignedOriginalFirmware struct { Blob Blob ImageOffset uint64 // contains filtered or unexported fields }
AlignedOriginalFirmware represents a part of the original image which is aligned with the DumpedFirmware image.
Often the only region we can dump from the target is BIOS region, while the original image usually consists of multiple regions (and the BIOS region is the last one). So the aligned image is a such image that has an offset (to start with the same thing as the dumped firmware) and the same length as the dumped firmware.
func NewAlignedOriginalFirmware ¶
func NewAlignedOriginalFirmware(fw *uefi.UEFI, offset uint64, blob Blob) AlignedOriginalFirmware
NewAlignedOriginalFirmware creates new AlignedOriginalImage object
`blob` is optional, if not provided, then fw.Buf() is used instead.
func (AlignedOriginalFirmware) UEFI ¶
func (ao AlignedOriginalFirmware) UEFI() *uefi.UEFI
UEFI returns an UEFI object of AlignedOriginalImage
type Analyzer ¶
type Analyzer[inputType any] interface { ID() AnalyzerID Analyze(context.Context, inputType) (*Report, error) }
Analyzer is an abstract interface that each analyzer should implement
type AnalyzerID ¶
type AnalyzerID string
AnalyzerID is a unique ID of every analyzer
TODO: consider replacing unique indexes with reflect.TypeOf(input) to have a single source of truth
type AssetID ¶
type AssetID int64
AssetID represents information about the asset id of the host that is being analyzed
type Blob ¶
type Blob interface {
Bytes() []byte
}
Blob is an interface of a huge blob. Semantically in this package it is just `[]byte`. But:
- Sometimes the consumers of this package may have constraints against passing large blobs directly as input. For example if we want analysis be storable and reproducible, in some infras it will store only an object ID in the input instead of the whole blob (and object itself will be stored in an object storage, like GitHub LFS or BlobStorage).
- Another reason to pass objectIDs instead of images themselves is to make cache more efficient, because calculated hashes for large objects might be too expensive.
WARNING! The object, implementing this interface should export enough data to uniquely identify the specific image. Internally package `analysis` hashes all the input to calculate the cache key. So if two different images exports exactly the same fields, then there will be INVALID DATA provided by the cache.
type BytesBlob ¶
type BytesBlob []byte
BytesBlob is a simple implementation of a Blob, based on a simple []byte.
type CachedValue ¶
type CachedValue struct { // TODO: consider replacing "reflect.Value" with just "any" Val reflect.Value Issues []Issue Err error }
CachedValue represents a value stored in DataCache
type DataCache ¶
type DataCache interface { // Get returns a cached object if found. inputHash could be nil, for cases when cache guarantees object uniqness for each type. // On of that cases is `uniqueTypeDataCache` that is used to store objects obtained for a single Analyser Get(t reflect.Type, inputHash *objhash.ObjHash) *CachedValue Set(t reflect.Type, inputHash objhash.ObjHash, val *CachedValue) }
DataCache represents an interface for a cache used in analysis package
func NewDataCache ¶
func NewDataCache() DataCache
NewDataCache creates a new multithreaded implementation of DataCache
type DataCalculator ¶
type DataCalculator struct {
// contains filtered or unexported fields
}
DataCalculator is a handler which resolves missing values for the analyzers using the given values
func NewDataCalculator ¶
func NewDataCalculator(cacheSize int) (*DataCalculator, error)
NewDataCalculator creates a new DataCalculator object
type DataCalculatorInterface ¶
type DataCalculatorInterface interface {
Calculate(ctx context.Context, t reflect.Type, in Input, cache DataCache) (reflect.Value, []Issue, error)
}
DataCalculatorInterface calculates intermediate results that could be reused, like: measurements flow, fixed registers
type ErrAnalyze ¶
type ErrAnalyze struct {
Err error
}
ErrAnalyze means got an error from calling Analyze().
func (ErrAnalyze) Unwrap ¶
func (e ErrAnalyze) Unwrap() error
Unwrap is used by errors.Is and errors.As.
type ErrCalcNotSupported ¶
type ErrCalcNotSupported struct {
// contains filtered or unexported fields
}
ErrCalcNotSupported determines a situation when input data calculator doesn't support the type
func (ErrCalcNotSupported) Error ¶
func (e ErrCalcNotSupported) Error() string
type ErrFailedCalcInput ¶
ErrFailedCalcInput determines a situation when input value should be calculated and that calculation failed
func (ErrFailedCalcInput) Error ¶
func (e ErrFailedCalcInput) Error() string
func (ErrFailedCalcInput) Unwrap ¶
func (e ErrFailedCalcInput) Unwrap() error
type ErrMissingInput ¶
type ErrMissingInput struct {
// contains filtered or unexported fields
}
ErrMissingInput determines situation when input needed by analyzer is missing
func (ErrMissingInput) Error ¶
func (e ErrMissingInput) Error() string
type ErrNotApplicable ¶
type ErrNotApplicable struct {
Description string
}
ErrNotApplicable should be returned by analyzer to tell that it is not applicable for given input
func NewErrNotApplicable ¶
func NewErrNotApplicable(description string) ErrNotApplicable
NewErrNotApplicable creates a new ErrNotApplicable object
func (ErrNotApplicable) Error ¶
func (e ErrNotApplicable) Error() string
type ErrResolveInput ¶
type ErrResolveInput struct {
Err error
}
ErrResolveInput means it was unable to resolve input, required by the analyzer.
func (ErrResolveInput) Error ¶
func (e ErrResolveInput) Error() string
Error implements interface "error".
func (ErrResolveInput) Unwrap ¶
func (e ErrResolveInput) Unwrap() error
Unwrap is used by errors.Is and errors.As.
type ErrResolveValue ¶
ErrResolveValue means it was unable to resolve a value, required by the analyzer.
func (ErrResolveValue) Error ¶
func (e ErrResolveValue) Error() string
Error implements interface "error".
func (ErrResolveValue) Unwrap ¶
func (e ErrResolveValue) Unwrap() error
Unwrap is used by errors.Is and errors.As.
type ErrTypeIDNotRegistered ¶
type ErrTypeIDNotRegistered struct {
TypeID TypeID
}
ErrTypeIDNotRegistered means there was an attempt to serialize/deserialize a value of a type, not registered in the type register (see also function `RegisterType`).
func (ErrTypeIDNotRegistered) Error ¶
func (e ErrTypeIDNotRegistered) Error() string
Error implements interface "error".
type FixedRegisters ¶
FixedRegisters represents registers that have been fixed in accordance with other information obtained from the host
func NewFixedRegisters ¶
func NewFixedRegisters(regs registers.Registers) (FixedRegisters, error)
NewFixedRegisters creates new ActualRegisters object
func (FixedRegisters) CacheWrite ¶
func (fr FixedRegisters) CacheWrite(b *objhash.Builder) error
CacheWrite is an implementation of objhash.Custom interface
func (FixedRegisters) GetRegisters ¶
func (fr FixedRegisters) GetRegisters() registers.Registers
GetRegisters returns registers
type Input ¶
Input specifies input data for analysis
func (Input) AddActualBIOSInfo ¶
func (in Input) AddActualBIOSInfo(biosInfo ActualBIOSInfo) Input
AddActualBIOSInfo adds SMBIOS info about the actual BIOS firmware.
func (Input) AddActualFirmware ¶
AddActualFirmware adds the actual firmware image
func (Input) AddActualPCR0 ¶
AddActualPCR0 adds information about existing PCR0 value on a host
func (Input) AddActualRegisters ¶
func (in Input) AddActualRegisters(regs ActualRegisters) Input
AddActualRegisters adds the actual registers
func (Input) AddAssetID ¶
AddAssetID adds information about asset id of a host
func (Input) AddCustomValue ¶
AddCustomValue adds a custom value as some plugins take unique values
Note: register custom values through RegisterInputType, to make them
deserializable.
func (Input) AddOriginalBIOSInfo ¶
func (in Input) AddOriginalBIOSInfo(biosInfo OriginalBIOSInfo) Input
AddOriginalBIOSInfo adds SMBIOS info about the original BIOS firmware.
func (Input) AddOriginalFirmware ¶
AddOriginalFirmware adds the original firmware image
func (Input) AddTPMDevice ¶
func (in Input) AddTPMDevice(tpm tpmdetection.Type) Input
AddTPMDevice adds inormation about the TPM device
func (Input) AddTPMEventLog ¶
func (in Input) AddTPMEventLog(eventLog *tpmeventlog.TPMEventLog) Input
AddTPMEventLog adds information about the TPM event log
func (Input) ForceBootFlow ¶
func (in Input) ForceBootFlow(_flow bootflowtypes.Flow) Input
ForceBootFlow adds information about the bootflow
func (Input) MarshalJSON ¶
MarshalJSON implements json.Marshaler
func (*Input) Scan ¶
Scan implements database/sql.Scanner TODO: remove this from this package. Package `analysis` should be agnostic of this stuff.
func (*Input) UnmarshalJSON ¶
UnmarshalJSON implements json.Unmarshaler
type Issue ¶
type Issue struct { // Custom is a custom information provided for issue description. Should be serialisable Custom any // Severity tells how important is found issue Severity Severity // Description is a text description of a found problem Description string }
Issue describes a single found problem in firmware
type OriginalBIOSInfo ¶
OriginalBIOSInfo represents data stored in the SMBIOS of the original image.
func NewOriginalBIOSInfo ¶
func NewOriginalBIOSInfo(biosInfo dmidecode.BIOSInfo) *OriginalBIOSInfo
NewOriginalBIOSInfo creates a new instance of OriginalBIOSInfo
type OriginalFirmware ¶
type OriginalFirmware struct { Blob // contributes into cache key // contains filtered or unexported fields }
OriginalFirmware represents parsed original firmware (the one we get from the orig firmware table and expect to be installed on the host)
func NewOriginalFirmware ¶
func NewOriginalFirmware(fw *uefi.UEFI, blob Blob) OriginalFirmware
NewOriginalFirmware creates a new OriginalFirmware object from firmware.
`blob` is optional, if not provided, then fw.Buf() is used instead.
func (OriginalFirmware) UEFI ¶
func (of OriginalFirmware) UEFI() *uefi.UEFI
UEFI returns an UEFI object of OriginalFirmware
type OriginalFirmwareBlob ¶
type OriginalFirmwareBlob struct {
Blob
}
OriginalFirmwareBlob represents raw bytes of the original firmware image
func NewOriginalFirmwareBlob ¶
func NewOriginalFirmwareBlob(image Blob) OriginalFirmwareBlob
NewOriginalFirmwareBlob creates a new OriginalFirmwareBlob object
type ReferenceFirmware ¶
type ReferenceFirmware struct { Blob Blob ImageOffset uint64 // contains filtered or unexported fields }
ReferenceFirmware is a firmware used as the reference. It is the aligned original firmware if it is available, or just the actual firmware otherwise.
func NewReferenceFirmware ¶
func NewReferenceFirmware(ctx context.Context, alignedOriginalFirmware *AlignedOriginalFirmware, actualFirmware *ActualFirmware) (*ReferenceFirmware, error)
NewReferenceFirmware creates new ReferenceFirmware object.
If alignedOriginalFirmware is nil then actualFirmware will be used as the reference firmware.
func (ReferenceFirmware) UEFI ¶
func (rf ReferenceFirmware) UEFI() *uefi.UEFI
UEFI returns an UEFI object of AlignedOriginalImage
type Report ¶
type Report struct { // Custom is a custom information provided for report description. Should be serialisable Custom any // Errors is the list of errors. Issues []Issue // Comments is the list of additional messages, which are not considered errors. Comments []string }
Report is an outcome of every firmware analysis algorithm
TODO: consider using Go generics to specify the `Custom` field.
func ExecuteAnalyzer ¶
func ExecuteAnalyzer[analyzerInputType any]( ctx context.Context, dataCalculator DataCalculatorInterface, analyzer Analyzer[analyzerInputType], in Input, cache DataCache, ) (retReport *Report, retErr error)
ExecuteAnalyzer invokes analysis of a single given Analyzer
func (Report) MarshalJSON ¶
MarshalJSON implements json.Marshaler
func (*Report) Scan ¶
Scan implements database/sql.Scanner TODO: remove this from this package. Package `analysis` should be agnostic of this stuff.
func (*Report) UnmarshalJSON ¶
UnmarshalJSON implements json.Unmarshaler