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
Oct 31, 2016Cumulonimbus
Hi Kai,
what do you think to use this loop instead of three times the same code: (
~$i
always return -(i+1)
). codes are validated with values 0 -1 1 -2 2
...
for {set i 0; set result 0} {$i < 20 && !($result)} {incr i} {
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 result 1
break
}
}
}
I also replaced Valid / Invalid with 0 / 1
you can return status with [lindex {Invalid Valid} $result]