Private/BfdAuth.ps1

function Test-BfdAuth {
    # Verifies the RFC 5880 6.7 authentication section of a received control packet (not the sequence number).
    param([byte[]]$Packet, [string]$Type, [int]$KeyId, [string]$Key)
    $info = $script:BfdAuthTypes[$Type]
    if (-not $info -or $Packet.Length -lt 27) { return $false }
    $len = [int]$Packet[3]
    if (($Packet[1] -band 0x04) -eq 0 -or $Packet.Length -lt $len -or $len -lt 27) { return $false }
    if ($Packet[24] -ne $info.Code -or $Packet[26] -ne $KeyId) { return $false }
    $keyBytes = [Text.Encoding]::UTF8.GetBytes($Key)

    if ($Type -eq 'SimplePassword') {
        if ($Packet[25] -ne ($len - 24)) { return $false }
        $pw = [byte[]]$Packet[27..($len - 1)]
        return [Security.Cryptography.CryptographicOperations]::FixedTimeEquals($pw, $keyBytes)
    }

    $digestLen = $info.Length - 8
    if ($Packet[25] -ne $info.Length -or $len -ne (24 + $info.Length) -or $keyBytes.Length -gt $info.MaxKey -or $keyBytes.Length -eq 0) { return $false }
    $tmp = [byte[]]$Packet[0..($len - 1)]
    [Array]::Clear($tmp, 32, $digestLen)
    [Array]::Copy($keyBytes, 0, $tmp, 32, $keyBytes.Length)
    $calc = Get-BfdHash -Algorithm $info.Hash -Data $tmp
    [Security.Cryptography.CryptographicOperations]::FixedTimeEquals($calc, [byte[]]$Packet[32..($len - 1)])
}

function Test-BfdAuthSequence {
    # RFC 5880 6.7.3/6.7.4: keyed sequence in [last, last + 3 x DetectMult], meticulous strictly greater than last.
    param([uint32]$Sequence, [uint32]$Last, [bool]$Known, [bool]$Meticulous, [int]$DetectMult)
    if (-not $Known) { return $true }
    $diff = (([long]$Sequence + 4294967296 - [long]$Last) % 4294967296)
    $max = 3 * [Math]::Max(1, $DetectMult)
    if ($Meticulous) { return ($diff -ge 1 -and $diff -le $max) }
    $diff -le $max
}