Google Authenticator Verification iRule (TMOS v11.1+ optimized)
Problem this snippet solves: Hi Folks,
the provided iRule contains a TMOS v11.1+ compatible fork of the already existing and very lovely Google Authenticator verification iRules here on CodeShare....
Updated Jun 06, 2023
Version 2.0Kai_Wilke
My name is Kai Wilke and I'm working as a Principal Consultant for IT-Security at itacs GmbH - a German consulting company specialized in Microsoft Security cloud solutions, F5 customizations as well as for classic IT-Consulting.
You can find additional information about me and my work here:
https://devcentral.f5.com/articles/q-a-with-itacs-gmbhs-kai-wilke-devcentrals-featured-member-for-february-24890MVP
Stanislas_Piro2
Nov 02, 2016Cumulonimbus
Hi Kai,
You're right about the additional check... but I solved it by setting to variable $i the $static::ga_allowed_clock_skew_units value.
for {set i 0; set result 0} {$i < $static::ga_allowed_clock_skew_units} {incr i} {
for each value $i, check value of $i and (-$i -1) . the following values are checked :
$i = 0 --> 0, -1
$i = 1 --> 1, -2
$i = 2 --> 2, -3
foreach x "$i [expr {~$i}]" {
Perform verification of the provided ga(token) for time frame ga(clock) $x
Calculate hex encoded HMAC checksum value for wide-int value of time frame ga(clock) + x using ga(key) as secret
binary scan [CRYPTO::sign -alg $static::ga_hmac_mode -key $ga(key) [binary format W* [expr { $ga(clock) + $x }]]] H* ga(verify)
Parse ga(offset) based on the last nibble (= 4 bits / 1 hex) of the ga(verify) HMAC checksum and multiply with 2 for byte to hex conversation
set ga(offset) [expr { "0x[string index $ga(verify) end]" * 2 } ]
Parse (= 4 bytes / 8 hex) from ga(verify) starting at the ga(offset) value, then remove the most significant bit, perform the modulo 1000000 and format the result to a 6 digit number
set ga(verify) [format %06d [expr { ( "0x[string range $ga(verify) $ga(offset) [expr { $ga(offset) + 7 } ]]" & 0x7FFFFFFF ) % 1000000 } ]]
Compare ga(verify) with user provided ga(token) value
if { $ga(verify) equals $ga(token) } then {
The provided ga(token) is valid"
set i $static::ga_allowed_clock_skew_units
set result 1
break
}
}
}
no more additional check. to solve understanding issue, I added a comment line 🙂