// Copyright (c) StellaOps. All rights reserved.
// Licensed under BUSL-1.1. See LICENSE in the project root.
using StellaOps.BinaryIndex.Disassembly;
using System.Collections.Immutable;
namespace StellaOps.BinaryIndex.DeltaSig;
///
/// Signature generation options.
///
/// Include control flow graph metrics.
/// Include rolling chunk hashes for resilience.
/// Size of rolling chunks in bytes (default 2KB).
/// Hash algorithm to use (default sha256).
/// Include IR-level semantic fingerprints for optimization-resilient matching.
public sealed record SignatureOptions(
bool IncludeCfg = true,
bool IncludeChunks = true,
int ChunkSize = 2048,
string HashAlgorithm = "sha256",
bool IncludeSemantic = false);
///
/// Request for generating delta signatures from a binary.
///
public sealed record DeltaSignatureRequest
{
///
/// CVE identifier (e.g., CVE-2024-1234).
///
public required string Cve { get; init; }
///
/// Package name.
///
public required string Package { get; init; }
///
/// Shared object name (e.g., libssl.so.1.1).
///
public string? Soname { get; init; }
///
/// Target architecture (e.g., x86_64, aarch64).
///
public required string Arch { get; init; }
///
/// ABI (e.g., gnu, musl, android).
///
public string Abi { get; init; } = "gnu";
///
/// Symbol names to generate signatures for.
///
public required IReadOnlyList TargetSymbols { get; init; }
///
/// State of this signature: "vulnerable" or "patched".
///
public required string SignatureState { get; init; }
///
/// Signature generation options.
///
public SignatureOptions? Options { get; init; }
}
///
/// A complete delta signature for a binary.
///
public sealed record DeltaSignature
{
///
/// Unique identifier for this signature.
///
public string SignatureId { get; init; } = Guid.NewGuid().ToString("N");
///
/// Schema identifier for this signature format.
///
public string Schema { get; init; } = "stellaops.deltasig.v1";
///
/// Schema version.
///
public string SchemaVersion { get; init; } = "1.0.0";
///
/// CVE this signature is for.
///
public required string Cve { get; init; }
///
/// Package reference.
///
public required PackageRef Package { get; init; }
///
/// Target platform reference.
///
public required TargetRef Target { get; init; }
///
/// Normalization recipe used.
///
public required NormalizationRef Normalization { get; init; }
///
/// Signature state: "vulnerable" or "patched".
///
public required string SignatureState { get; init; }
///
/// Individual symbol signatures.
///
public required ImmutableArray Symbols { get; init; }
///
/// When this signature was generated (UTC).
///
public DateTimeOffset GeneratedAt { get; init; } = DateTimeOffset.UtcNow;
///
/// Additional metadata.
///
public IReadOnlyDictionary? Metadata { get; init; }
}
///
/// Package reference for a delta signature.
///
/// Package name.
/// Shared object name.
public sealed record PackageRef(string Name, string? Soname);
///
/// Target platform reference.
///
/// CPU architecture (x86_64, aarch64, etc.).
/// ABI (gnu, musl, android, etc.).
public sealed record TargetRef(string Arch, string Abi);
///
/// Normalization recipe reference for reproducibility.
///
/// Recipe identifier (e.g., elf.delta.norm.x64).
/// Recipe version.
/// List of normalization steps applied.
public sealed record NormalizationRef(
string RecipeId,
string RecipeVersion,
ImmutableArray Steps);
///
/// Signature for a single symbol (function).
///
public sealed record SymbolSignature
{
///
/// Symbol name.
///
public required string Name { get; init; }
///
/// Section containing the symbol (e.g., .text).
///
public string Scope { get; init; } = ".text";
///
/// Hash algorithm used.
///
public required string HashAlg { get; init; }
///
/// Hash of the normalized function as hex string.
///
public required string HashHex { get; init; }
///
/// Size of the normalized function in bytes.
///
public required int SizeBytes { get; init; }
///
/// Number of basic blocks in the control flow graph.
///
public int? CfgBbCount { get; init; }
///
/// Hash of the CFG structure (edges).
///
public string? CfgEdgeHash { get; init; }
///
/// Rolling chunk hashes for resilience against small changes.
///
public ImmutableArray? Chunks { get; init; }
///
/// Semantic fingerprint hash based on IR-level analysis (hex string).
/// Provides resilience against compiler optimizations and instruction reordering.
///
public string? SemanticHashHex { get; init; }
///
/// API calls extracted from semantic analysis (for semantic anchoring).
///
public ImmutableArray? SemanticApiCalls { get; init; }
}
///
/// Hash of a chunk within a function for resilience.
///
/// Offset from function start.
/// Chunk size in bytes.
/// Hash of the chunk as hex string.
public sealed record ChunkHash(int Offset, int Size, string HashHex);
///
/// Result of matching a binary against delta signatures.
///
public sealed record MatchResult
{
///
/// Whether a match was found.
///
public required bool Matched { get; init; }
///
/// The CVE that matched.
///
public string? Cve { get; init; }
///
/// The signature state that matched (vulnerable/patched).
///
public string? SignatureState { get; init; }
///
/// Confidence score (0.0 - 1.0).
///
public double Confidence { get; init; }
///
/// Individual symbol match results.
///
public ImmutableArray SymbolMatches { get; init; } = [];
///
/// Explanation of the match result.
///
public string? Explanation { get; init; }
}
///
/// Match result for a single symbol.
///
public sealed record SymbolMatchResult
{
///
/// Symbol name.
///
public required string SymbolName { get; init; }
///
/// Whether the symbol hash matched exactly.
///
public required bool ExactMatch { get; init; }
///
/// Number of chunk hashes that matched (partial match).
///
public int ChunksMatched { get; init; }
///
/// Total chunks in the signature.
///
public int ChunksTotal { get; init; }
///
/// Match confidence (0.0 - 1.0).
///
public double Confidence { get; init; }
// ====== CHANGE TRACKING FIELDS ======
///
/// Type of change detected.
///
public SymbolChangeType ChangeType { get; init; } = SymbolChangeType.Unchanged;
///
/// Size delta in bytes (positive = larger, negative = smaller).
///
public int SizeDelta { get; init; }
///
/// CFG basic block count delta (if available).
///
public int? CfgBlockDelta { get; init; }
///
/// Indices of chunks that matched (for partial match analysis).
///
public ImmutableArray MatchedChunkIndices { get; init; } = [];
///
/// Human-readable explanation of the change.
///
public string? ChangeExplanation { get; init; }
///
/// Hash of the "from" version (before change).
///
public string? FromHash { get; init; }
///
/// Hash of the "to" version (after change).
///
public string? ToHash { get; init; }
///
/// Method used for matching (CFGHash, InstructionHash, SemanticHash, ChunkHash).
///
public string? MatchMethod { get; init; }
}
///
/// Type of symbol change detected.
///
public enum SymbolChangeType
{
///
/// No change detected.
///
Unchanged,
///
/// Symbol was added (not present in "from" version).
///
Added,
///
/// Symbol was removed (not present in "to" version).
///
Removed,
///
/// Symbol was modified (hash changed).
///
Modified,
///
/// Symbol was patched (security fix applied, verified).
///
Patched
}
///
/// Result of authoring signatures from vulnerable and patched binaries.
///
public sealed record AuthoringResult
{
///
/// Whether authoring succeeded.
///
public required bool Success { get; init; }
///
/// Signature for the vulnerable binary.
///
public DeltaSignature? VulnerableSignature { get; init; }
///
/// Signature for the patched binary.
///
public DeltaSignature? PatchedSignature { get; init; }
///
/// Symbols that differ between vulnerable and patched.
///
public ImmutableArray DifferingSymbols { get; init; } = [];
///
/// Error message if authoring failed.
///
public string? Error { get; init; }
}
///
/// Result of comparing two delta signatures.
///
public sealed record DeltaComparisonResult
{
///
/// Identifier for the "from" signature.
///
public required string FromSignatureId { get; init; }
///
/// Identifier for the "to" signature.
///
public required string ToSignatureId { get; init; }
///
/// Individual symbol comparison results.
///
public ImmutableArray SymbolResults { get; init; } = [];
///
/// Summary of the comparison.
///
public required DeltaComparisonSummary Summary { get; init; }
}
///
/// Summary of a delta comparison between two signatures.
///
public sealed record DeltaComparisonSummary
{
///
/// Total number of symbols compared.
///
public int TotalSymbols { get; init; }
///
/// Number of unchanged symbols.
///
public int UnchangedSymbols { get; init; }
///
/// Number of added symbols.
///
public int AddedSymbols { get; init; }
///
/// Number of removed symbols.
///
public int RemovedSymbols { get; init; }
///
/// Number of modified symbols.
///
public int ModifiedSymbols { get; init; }
///
/// Number of patched symbols (security fixes).
///
public int PatchedSymbols { get; init; }
///
/// Average confidence across all symbol comparisons.
///
public double AverageConfidence { get; init; }
///
/// Total size delta in bytes.
///
public int TotalSizeDelta { get; init; }
}