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