mirror of
https://github.com/adulau/ootp.git
synced 2024-11-22 10:07:12 +00:00
876 lines
20 KiB
QBasic
876 lines
20 KiB
QBasic
|
'
|
||
|
' Copyright (c) 2005,2006 Mark Fullmer
|
||
|
' Copyright (c) 2009 Mark Fullmer and the Ohio State University
|
||
|
' All rights reserved.
|
||
|
'
|
||
|
' Redistribution and use in source and binary forms, with or without
|
||
|
' modification, are permitted provided that the following conditions
|
||
|
' are met:
|
||
|
' 1. Redistributions of source code must retain the above copyright
|
||
|
' notice, this list of conditions and the following disclaimer.
|
||
|
' 2. Redistributions in binary form must reproduce the above copyright
|
||
|
' notice, this list of conditions and the following disclaimer in the
|
||
|
' documentation and/or other materials provided with the distribution.
|
||
|
'
|
||
|
' THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||
|
' ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
' IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
' ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||
|
' FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
|
' DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||
|
' OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
|
' HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
' LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
|
' OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
|
' SUCH DAMAGE.
|
||
|
'
|
||
|
' $Id: HOTPC.BAS 13 2009-11-26 16:37:03Z maf $
|
||
|
'
|
||
|
#include "sha-1.def"
|
||
|
#include "preader.def"
|
||
|
#include "AlgID.DEF"
|
||
|
#include "commands.def"
|
||
|
#include "hotp.def"
|
||
|
|
||
|
Option Explicit
|
||
|
|
||
|
' number of keys/hosts - max 254. 255 is reserved. Index is 8 bits.
|
||
|
Const HOTPNum = 85
|
||
|
|
||
|
' HOTPCodeVersion notes:
|
||
|
' Rev 1 - first production version - feb 2006
|
||
|
' Rev 2 - disable AdminMode on first usage - safety net
|
||
|
' if left on by mistake.
|
||
|
' Rev 3 - Count32 commands
|
||
|
' - conditional compile commands
|
||
|
' - Get/Set/Test naming standardize
|
||
|
' Rev 4 - release of Rev3
|
||
|
' Rev 5 - renumber commands, readerKey, getCapabilities
|
||
|
' - ClearALL, checkReaderKey
|
||
|
' Rev 6 - release Rev5
|
||
|
|
||
|
' Code version
|
||
|
Const HOTPCodeVersion = 6
|
||
|
|
||
|
' Capabilities (conditionally compiled in functions)
|
||
|
eeprom Capabilities as Long = CAPSETHOST + CAPGETHOST + CAPGETHOSTNAME + _
|
||
|
CAPGETHOTP + CAPSETADMINMODE + _
|
||
|
CAPSETBALANCECARDINDEX + CAPSETPIN + _
|
||
|
CAPTESTPIN + CAPGETVERSION + _
|
||
|
CAPSETADMINKEY + CAPSETHOST32 + _
|
||
|
CAPGETHOST32 + CAPGETHOTPCOUNT32 + _
|
||
|
CAPGETHOTPHOST + CAPGETHOTPHOSTCOUNT32 + _
|
||
|
CAPPRDISPLAY + CAPCLEARALL + CAPSETREADERKEY
|
||
|
|
||
|
Const DefaultPIN = "28165"
|
||
|
|
||
|
' Default Admin Key
|
||
|
eeprom AdminKey as String*20 = "00000000000000000000"
|
||
|
|
||
|
' HOTPK and its derivatives
|
||
|
' default Key "00000000000000000000"
|
||
|
' KeyI is Key XOR input pad (0x36)
|
||
|
' IPAD44 is 0x36 repeated 44 times
|
||
|
' KeyO is Key XOR output pad (0x5c)
|
||
|
' OPAD44 is 0x5c repeated 44 times.
|
||
|
|
||
|
' Note that only the I and O versions of the keys
|
||
|
' are stored -- which is all that's needed.
|
||
|
' An alternative implementation could choose to store
|
||
|
' the key and compute the I and O versions at run time
|
||
|
' this would use less EEPROM space at the cost of more
|
||
|
' CPU cycles (and less battery life) to compute a HOTP
|
||
|
|
||
|
eeprom HOTPKeyI(HOTPNum) as string*20 = &H06,&H06,&H06,&H06,&H06,&H06,&H06, _
|
||
|
&H06,&H06,&H06,&H06,&H06,&H06,&H06, _
|
||
|
&H06,&H06,&H06,&H06,&H06,&H06
|
||
|
|
||
|
|
||
|
eeprom HOTPKeyO(HOTPNum) as string*20 = &H6C,&H6C,&H6C,&H6C,&H6C,&H6C,&H6C, _
|
||
|
&H6C,&H6C,&H6C,&H6C,&H6C,&H6C,&H6C, _
|
||
|
&H6C,&H6C,&H6C,&H6C,&H6C,&H6C
|
||
|
|
||
|
eeprom HOTPHost(HOTPNum) as string*12
|
||
|
|
||
|
eeprom HOTPCount32(HOTPNum) as Long
|
||
|
|
||
|
|
||
|
' Input pad
|
||
|
eeprom IPAD44 as string*44 = &H36,&H36,&H36,&H36,&H36,&H36,&H36,&H36,&H36, _
|
||
|
&H36,&H36,&H36,&H36,&H36,&H36,&H36,&H36,&H36, _
|
||
|
&H36,&H36,&H36,&H36,&H36,&H36,&H36,&H36,&H36, _
|
||
|
&H36,&H36,&H36,&H36,&H36,&H36,&H36,&H36,&H36, _
|
||
|
&H36,&H36,&H36,&H36,&H36,&H36,&H36,&H36
|
||
|
|
||
|
|
||
|
' Output pad
|
||
|
eeprom OPAD44 as string*44 = &H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C, _
|
||
|
&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C, _
|
||
|
&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C, _
|
||
|
&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C, _
|
||
|
&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C,&H5C
|
||
|
|
||
|
' Temporary message digest (inner)
|
||
|
eeprom md1 as string*20
|
||
|
|
||
|
' PIN - used to deter unauthorized use
|
||
|
eeprom PIN as string*5 = DefaultPIN
|
||
|
|
||
|
' Reader Key. Weak authentication for reader
|
||
|
eeprom readerKey as string*5 = "00000"
|
||
|
|
||
|
' The balance card can only use one of the host definitions.
|
||
|
eeprom BalanceCardIndex = 255 ' Disabled
|
||
|
|
||
|
' if AdminMode is not set some commands require a valid PIN to work.
|
||
|
eeprom AdminMode as Byte = 1
|
||
|
|
||
|
' Keep track of PIN failures
|
||
|
eeprom PINFailCount as Byte = 0
|
||
|
eeprom readerKeyFailCount as Byte = 0
|
||
|
Const MaxPINFail = 10
|
||
|
Const MaxReaderKeyFail = 2
|
||
|
|
||
|
Function CheckPIN(myPIN as string*5) as Byte
|
||
|
|
||
|
if AdminMode = 1 then
|
||
|
CheckPIN = 0 ' success
|
||
|
PINFailCount = 0 ' reset
|
||
|
else
|
||
|
if PINFailCount >= MaxPINFail then
|
||
|
CheckPIN = 2 ' fail
|
||
|
else
|
||
|
if myPIN <> PIN then
|
||
|
CheckPIN = 1 ' fail
|
||
|
PINFailCount = PINFailCount + 1
|
||
|
else
|
||
|
CheckPIN = 0 ' Success
|
||
|
PINFailCount = 0
|
||
|
end if
|
||
|
end if
|
||
|
end if
|
||
|
end Function
|
||
|
|
||
|
Function CheckReaderKey(idx as Byte, myKey as String*5) as Byte
|
||
|
if (Asc(HOTPHost(idx)(2)) AND &H80) then
|
||
|
if myKey <> readerKey then
|
||
|
readerKeyFailCount = readerKeyFailCount + 1
|
||
|
if (readerKeyFailCount >= MAXReaderKeyFail) then
|
||
|
PINFailCount = MaxPINFail ' Lock card
|
||
|
end if
|
||
|
CheckReaderKey = 1 ' Fail
|
||
|
else
|
||
|
readerKeyFailCount = 0
|
||
|
CheckReaderKey = 0 ' Success
|
||
|
end if
|
||
|
else
|
||
|
CheckReaderKey = 0 'Success
|
||
|
end if
|
||
|
end Function
|
||
|
|
||
|
Function CheckAdmin() as Byte
|
||
|
if AdminMode <> 1 then
|
||
|
CheckAdmin = 1 ' fail
|
||
|
else
|
||
|
CheckAdmin = 0 ' success
|
||
|
end if
|
||
|
end Function
|
||
|
|
||
|
Function CheckIndex(Idx as Byte) as Byte
|
||
|
if Idx > HOTPNum then
|
||
|
CheckIndex = 1
|
||
|
else
|
||
|
CheckIndex = 0
|
||
|
end if
|
||
|
end function
|
||
|
|
||
|
'
|
||
|
' The balance reader doesn't wait long for a reponse so the HMAC must be
|
||
|
' broken up into steps
|
||
|
'
|
||
|
' HMAC as defined in RFC2104 is H(K XOR opad, H(K XOR ipad, text))
|
||
|
' where K is the key
|
||
|
' ipad=0x36
|
||
|
' opad=0x5c
|
||
|
' H=SHA-160
|
||
|
' text=Count
|
||
|
'
|
||
|
|
||
|
#ifdef ENABLEPRDISPLAY
|
||
|
Command &HC8 &H00 PRDisplay(RecordNumber as Byte, DataFormat as Byte, _
|
||
|
DigitCount as Byte,DecimalPoint as Byte, _
|
||
|
Delay as Byte, MoreData as Byte, _
|
||
|
Data as String)
|
||
|
|
||
|
private str11 as string*11
|
||
|
private str8 as string*8
|
||
|
private str4 as string*4 at str8+4
|
||
|
private low as long at str8+4
|
||
|
private high as long at str8
|
||
|
|
||
|
if BalanceCardIndex = 255 then
|
||
|
data = "Not Enabled"
|
||
|
dataFormat = PRAlpha
|
||
|
exit command
|
||
|
end if
|
||
|
|
||
|
select case RecordNumber
|
||
|
|
||
|
case 0
|
||
|
DataFormat = PRAlpha
|
||
|
DigitCount = 0
|
||
|
DecimalPoint = 0
|
||
|
Delay = 1
|
||
|
MoreData = PRMoreData
|
||
|
|
||
|
' disable admin mode on first use.
|
||
|
if (AdminMode = 1) then
|
||
|
AdminMode = 0
|
||
|
end if
|
||
|
|
||
|
low = HOTPCount32(0)
|
||
|
|
||
|
' Display VER1-count
|
||
|
data = "VER1-" + hex$(low)
|
||
|
|
||
|
' start inner hash of HMAC SHA-160(K XOR ipad,text)
|
||
|
call ShaStart()
|
||
|
call ShaAppend(HOTPKeyI(0))
|
||
|
|
||
|
case 1
|
||
|
DataFormat = PRAlpha
|
||
|
DigitCount = 0
|
||
|
DecimalPoint = 6
|
||
|
Delay = 1
|
||
|
MoreData = PRMoreData
|
||
|
data = "HOTP"
|
||
|
|
||
|
low = HOTPcount(0)
|
||
|
|
||
|
' inner hash still working
|
||
|
call ShaAppend(IPAD44)
|
||
|
call ShaAppend(str8)
|
||
|
|
||
|
case 2
|
||
|
DataFormat = PRAlpha
|
||
|
DigitCount = 0
|
||
|
DecimalPoint = 5
|
||
|
Delay = 1
|
||
|
MoreData = PRMoreData
|
||
|
Data = "HOTP"
|
||
|
|
||
|
' done with inner hash. Store temp result in md1
|
||
|
md1 = ShaEnd()
|
||
|
|
||
|
case 3
|
||
|
DataFormat = PRAlpha
|
||
|
DigitCount = 0
|
||
|
DecimalPoint = 4
|
||
|
Delay = 1
|
||
|
MoreData = PRMoreData
|
||
|
Data = "HOTP"
|
||
|
|
||
|
' start outer hash H(K XOR opad, inner)
|
||
|
call ShaStart()
|
||
|
call ShaAppend(HOTPKeyO(0))
|
||
|
|
||
|
case 4
|
||
|
DataFormat = PRAlpha
|
||
|
DigitCount = 0
|
||
|
DecimalPoint = 3
|
||
|
Delay = 1
|
||
|
MoreData = PRMoreData
|
||
|
data = "HOTP"
|
||
|
|
||
|
' outer still working.
|
||
|
call ShaAppend(OPAD44)
|
||
|
|
||
|
case 5
|
||
|
DataFormat = PRAlpha
|
||
|
DigitCount = 0
|
||
|
DecimalPoint = 2
|
||
|
Delay = 1
|
||
|
MoreData = PRMoreData
|
||
|
data = "HOTP"
|
||
|
|
||
|
' outer still working...
|
||
|
call ShaAppend(md1)
|
||
|
|
||
|
' Increment Count just before displaying result.
|
||
|
|
||
|
Disable OverflowCheck
|
||
|
HOTPCount32(0) = HOTPCount32(0) + 1
|
||
|
Enable OverflowCheck
|
||
|
|
||
|
case 6
|
||
|
DataFormat = PRHex
|
||
|
DigitCount = 10
|
||
|
DecimalPoint = 0
|
||
|
Delay = 10000 / PRDelayUnits ' display 10 seconds
|
||
|
MoreData = PRNoMoreData
|
||
|
|
||
|
' finish with outer, display top 40 bits in hex (no leading 0's).
|
||
|
str11 = "000" + left$(ShaEnd(),8)
|
||
|
data = left$(str11,8)
|
||
|
|
||
|
case else
|
||
|
' should not happen
|
||
|
SW1SW2=swDataNotFound
|
||
|
end select
|
||
|
End Command
|
||
|
#endif ' ENABLECPRDISPLAY
|
||
|
|
||
|
#ifdef ENABLECSETHOST
|
||
|
command &H80 &H40 SetHost(Idx as Byte, Count as Integer, _
|
||
|
HostName as String*12, HOTPKey as String*20)
|
||
|
|
||
|
private tmp as string*20
|
||
|
private tmpb1 as long at tmp
|
||
|
private tmpb2 as long at tmp+4
|
||
|
private tmpb3 as long at tmp+8
|
||
|
private tmpb4 as long at tmp+12
|
||
|
private tmpb5 as long at tmp+16
|
||
|
|
||
|
if CheckAdmin() <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
if CheckIndex(Idx) <> 0 then
|
||
|
SW1SW2 = swDataNotFound
|
||
|
Exit
|
||
|
End if
|
||
|
|
||
|
' store K
|
||
|
' HOTPKey(n) = K
|
||
|
|
||
|
' store K XOR IPAD
|
||
|
tmp = HOTPKey
|
||
|
tmpb1 = tmpb1 xor &H36363636
|
||
|
tmpb2 = tmpb2 xor &H36363636
|
||
|
tmpb3 = tmpb3 xor &H36363636
|
||
|
tmpb4 = tmpb4 xor &H36363636
|
||
|
tmpb5 = tmpb5 xor &H36363636
|
||
|
HOTPKeyI(idx) = tmp
|
||
|
|
||
|
' store K XOR OPAD
|
||
|
tmp = HOTPKey
|
||
|
tmpb1 = tmpb1 xor &H5C5C5C5C
|
||
|
tmpb2 = tmpb2 xor &H5C5C5C5C
|
||
|
tmpb3 = tmpb3 xor &H5C5C5C5C
|
||
|
tmpb4 = tmpb4 xor &H5C5C5C5C
|
||
|
tmpb5 = tmpb5 xor &H5C5C5C5C
|
||
|
HOTPKeyO(idx) = tmp
|
||
|
|
||
|
HOTPCount32(Idx) = Count
|
||
|
HOTPHost(Idx) = HostName
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECSETHOST
|
||
|
|
||
|
#ifdef ENABLECGETHOST
|
||
|
' GetHost
|
||
|
command &H80 &H42 GetHost(Idx as Byte, Count as Integer, _
|
||
|
HostName as String*12, HOTPKey as String*20)
|
||
|
|
||
|
private tmp as string*20
|
||
|
private tmpb1 as long at tmp
|
||
|
private tmpb2 as long at tmp+4
|
||
|
private tmpb3 as long at tmp+8
|
||
|
private tmpb4 as long at tmp+12
|
||
|
private tmpb5 as long at tmp+16
|
||
|
|
||
|
if CheckAdmin() <> 0 then
|
||
|
sw1sw2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
if CheckIndex(Idx) <> 0 then
|
||
|
sw1sw2 = swDataNotFound
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
Count = HOTPCount32(Idx)
|
||
|
HostName = HOTPHost(Idx)
|
||
|
|
||
|
' load K XOR IPAD
|
||
|
' could also do this with OPAD...
|
||
|
tmp = HOTPKeyI(Idx)
|
||
|
tmpb1 = tmpb1 xor &H36363636
|
||
|
tmpb2 = tmpb2 xor &H36363636
|
||
|
tmpb3 = tmpb3 xor &H36363636
|
||
|
tmpb4 = tmpb4 xor &H36363636
|
||
|
tmpb5 = tmpb5 xor &H36363636
|
||
|
|
||
|
HOTPKey = tmp
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECGETHOST
|
||
|
|
||
|
#ifdef ENABLECGETHOSTNAME
|
||
|
command &H80 &H44 GetHostName(Idx as Byte, myPIN as String*5,_
|
||
|
HostName as String*12)
|
||
|
|
||
|
if CheckPIN(myPIN) <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
if CheckIndex(Idx) <> 0 then
|
||
|
SW1SW2 = swDataNotFound
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
HostName = HOTPHost(idx)
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECGETHOSTNAME
|
||
|
|
||
|
#ifdef ENABLECGETHOTP
|
||
|
command &H80 &H46 GetHOTP(Idx as Byte, myPIN as String*5, HOTP as String*5)
|
||
|
|
||
|
private str8 as string*8
|
||
|
private low as long at str8+4
|
||
|
|
||
|
if CheckPIN(myPIN) <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
' disable admin mode on first use.
|
||
|
if (AdminMode = 1) then
|
||
|
AdminMode = 0
|
||
|
end if
|
||
|
|
||
|
' don't allow operations with default pin
|
||
|
if myPIN = DefaultPIN then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
' Check reader access
|
||
|
if CheckReaderKey(Idx, HOTP) <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
if CheckIndex(Idx) <> 0 then
|
||
|
SW1SW2 = swDataNotFound
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
low = HOTPCount32(idx)
|
||
|
|
||
|
call ShaStart()
|
||
|
call ShaAppend(HOTPKeyI(idx))
|
||
|
call ShaAppend(IPAD44)
|
||
|
call ShaAppend(str8)
|
||
|
md1 = ShaEnd()
|
||
|
|
||
|
call ShaStart()
|
||
|
call ShaAppend(HOTPKeyO(idx))
|
||
|
call ShaAppend(OPAD44)
|
||
|
call ShaAppend(md1)
|
||
|
|
||
|
Disable OverflowCheck
|
||
|
HOTPCount32(idx) = low + 1
|
||
|
Enable OverflowCheck
|
||
|
|
||
|
HOTP = left$(ShaEnd(),5)
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECGETHOTP
|
||
|
|
||
|
#ifdef ENABLECSETADMINMODE
|
||
|
command &H80 &H48 SetAdminMode(Mode as Byte, K as String*20)
|
||
|
|
||
|
if K <> AdminKey then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
else
|
||
|
AdminMode = Mode
|
||
|
end if
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECSETADMINMODE
|
||
|
|
||
|
#ifdef ENABLECSETBALANCECARDINDEX
|
||
|
command &H80 &H4A SetBalanceCardIndex(Idx as Byte)
|
||
|
|
||
|
if CheckAdmin() <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
exit
|
||
|
else
|
||
|
BalanceCardIndex = Idx
|
||
|
end if
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECSETBALANCECARDINDEX
|
||
|
|
||
|
#ifdef ENABLECSETPIN
|
||
|
command &H80 &H4C SetPIN(myPIN as String*5, newPIN as String*5)
|
||
|
|
||
|
if CheckPIN(myPIN) <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
else
|
||
|
PIN = newPIN
|
||
|
end if
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECSETPIN
|
||
|
|
||
|
#ifdef ENABLECTESTPIN
|
||
|
command &H80 &H4E TestPIN(myPIN as String*5)
|
||
|
private t as Byte
|
||
|
|
||
|
t = CheckPIN(myPIN)
|
||
|
|
||
|
if t <> 0 then
|
||
|
if t = 2 then
|
||
|
SW1SW2 = swBadAuthenticate ' too many tries
|
||
|
else
|
||
|
SW1SW2 = swAccessDenied
|
||
|
end if
|
||
|
end if
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECTESTPIN
|
||
|
|
||
|
#ifdef ENABLECGETVERSION
|
||
|
command &H80 &H50 GetVersion(V as Byte)
|
||
|
|
||
|
V = HOTPCodeVersion
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECGETVERSION
|
||
|
|
||
|
#ifdef ENABLECSETADMINKEY
|
||
|
command &H80 &H52 SetAdminKey(K as String*20)
|
||
|
|
||
|
if CheckAdmin() <> 0 then
|
||
|
sw1sw2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
AdminKey = K
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECSETADMINKEY
|
||
|
|
||
|
#ifdef ENABLECSETHOST32
|
||
|
command &H80 &H54 SetHost32(Idx as Byte, Count32 as Long,_
|
||
|
HostName as String*12, HOTPKey as String*20)
|
||
|
|
||
|
private tmp as string*20
|
||
|
private tmpb1 as long at tmp
|
||
|
private tmpb2 as long at tmp+4
|
||
|
private tmpb3 as long at tmp+8
|
||
|
private tmpb4 as long at tmp+12
|
||
|
private tmpb5 as long at tmp+16
|
||
|
|
||
|
if CheckAdmin() <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
if CheckIndex(Idx) <> 0 then
|
||
|
SW1SW2 = swDataNotFound
|
||
|
Exit
|
||
|
End if
|
||
|
|
||
|
HOTPCount32(Idx) = Count32
|
||
|
HOTPHost(Idx) = HostName
|
||
|
|
||
|
' store K
|
||
|
' HOTPKey(n) = K
|
||
|
|
||
|
' store K XOR IPAD
|
||
|
tmp = HOTPKey
|
||
|
tmpb1 = tmpb1 xor &H36363636
|
||
|
tmpb2 = tmpb2 xor &H36363636
|
||
|
tmpb3 = tmpb3 xor &H36363636
|
||
|
tmpb4 = tmpb4 xor &H36363636
|
||
|
tmpb5 = tmpb5 xor &H36363636
|
||
|
HOTPKeyI(idx) = tmp
|
||
|
|
||
|
' store K XOR OPAD
|
||
|
tmp = HOTPKey
|
||
|
tmpb1 = tmpb1 xor &H5C5C5C5C
|
||
|
tmpb2 = tmpb2 xor &H5C5C5C5C
|
||
|
tmpb3 = tmpb3 xor &H5C5C5C5C
|
||
|
tmpb4 = tmpb4 xor &H5C5C5C5C
|
||
|
tmpb5 = tmpb5 xor &H5C5C5C5C
|
||
|
HOTPKeyO(idx) = tmp
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECSETHOST32
|
||
|
|
||
|
#ifdef ENABLECGETHOST32
|
||
|
command &H80 &H56 GetHost32(Idx as Byte, Count32 as Long,_
|
||
|
HostName as String*12, HOTPKey as String*20)
|
||
|
|
||
|
private tmp as string*20
|
||
|
private tmpb1 as long at tmp
|
||
|
private tmpb2 as long at tmp+4
|
||
|
private tmpb3 as long at tmp+8
|
||
|
private tmpb4 as long at tmp+12
|
||
|
private tmpb5 as long at tmp+16
|
||
|
|
||
|
if CheckAdmin() <> 0 then
|
||
|
sw1sw2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
if CheckIndex(Idx) <> 0 then
|
||
|
sw1sw2 = swDataNotFound
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
Count32 = HOTPCount32(Idx)
|
||
|
HostName = HOTPHost(Idx)
|
||
|
|
||
|
' load K XOR IPAD
|
||
|
' could also do this with OPAD...
|
||
|
tmp = HOTPKeyI(Idx)
|
||
|
tmpb1 = tmpb1 xor &H36363636
|
||
|
tmpb2 = tmpb2 xor &H36363636
|
||
|
tmpb3 = tmpb3 xor &H36363636
|
||
|
tmpb4 = tmpb4 xor &H36363636
|
||
|
tmpb5 = tmpb5 xor &H36363636
|
||
|
|
||
|
HOTPKey = tmp
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECGETHOST32
|
||
|
|
||
|
#ifdef ENABLECGETHOTPCOUNT32
|
||
|
command &H80 &H58 GetHOTPCount32(Idx as Byte, myPIN as String*5,_
|
||
|
Count32 as Long, HOTP as String*5)
|
||
|
|
||
|
private str8 as string*8
|
||
|
private low as long at str8+4
|
||
|
|
||
|
if CheckPIN(myPIN) <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
' disable admin mode on first use.
|
||
|
if (AdminMode = 1) then
|
||
|
AdminMode = 0
|
||
|
end if
|
||
|
|
||
|
' don't allow operations with default pin
|
||
|
if myPIN = DefaultPIN then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
' Check reader access
|
||
|
if CheckReaderKey(Idx, HOTP) <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
if CheckIndex(Idx) <> 0 then
|
||
|
SW1SW2 = swDataNotFound
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
' when Count32 == 0, use stored count
|
||
|
if Count32 <> 0 then
|
||
|
low = Count32
|
||
|
else
|
||
|
low = HOTPCount32(idx)
|
||
|
end if
|
||
|
|
||
|
call ShaStart()
|
||
|
call ShaAppend(HOTPKeyI(idx))
|
||
|
call ShaAppend(IPAD44)
|
||
|
call ShaAppend(str8)
|
||
|
md1 = ShaEnd()
|
||
|
|
||
|
call ShaStart()
|
||
|
call ShaAppend(HOTPKeyO(idx))
|
||
|
call ShaAppend(OPAD44)
|
||
|
call ShaAppend(md1)
|
||
|
|
||
|
Disable OverflowCheck
|
||
|
HOTPCount32(idx) = low + 1
|
||
|
Enable OverflowCheck
|
||
|
|
||
|
HOTP = left$(ShaEnd(),5)
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABE_GETHOTPCOUNT32
|
||
|
|
||
|
#ifdef ENABLECGETHOTPHOST
|
||
|
command &H80 &H5A GetHOTPHost(Idx as Byte, myPIN as String*5,_
|
||
|
HOTP as String*5, HostName as String*12)
|
||
|
|
||
|
private str8 as string*8
|
||
|
private low as long at str8+4
|
||
|
|
||
|
if CheckPIN(myPIN) <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
' disable admin mode on first use.
|
||
|
if (AdminMode = 1) then
|
||
|
AdminMode = 0
|
||
|
end if
|
||
|
|
||
|
' don't allow operations with default pin
|
||
|
if myPIN = DefaultPIN then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
' Check reader access
|
||
|
if CheckReaderKey(Idx, HOTP) <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
if CheckIndex(Idx) <> 0 then
|
||
|
SW1SW2 = swDataNotFound
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
low = HOTPCount32(idx)
|
||
|
|
||
|
call ShaStart()
|
||
|
call ShaAppend(HOTPKeyI(idx))
|
||
|
call ShaAppend(IPAD44)
|
||
|
call ShaAppend(str8)
|
||
|
md1 = ShaEnd()
|
||
|
|
||
|
call ShaStart()
|
||
|
call ShaAppend(HOTPKeyO(idx))
|
||
|
call ShaAppend(OPAD44)
|
||
|
call ShaAppend(md1)
|
||
|
|
||
|
Disable OverflowCheck
|
||
|
HOTPCount32(idx) = low + 1
|
||
|
Enable OverflowCheck
|
||
|
|
||
|
HOTP = left$(ShaEnd(),5)
|
||
|
HostName = HOTPHost(Idx)
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECGETHOTPHOST
|
||
|
|
||
|
#ifdef ENABLECGETHOTPHOSTCOUNT32
|
||
|
command &H80 &H5C GetHOTPHostCount32(Idx as Byte, myPIN as String*5,_
|
||
|
Count32 as Long, HOTP as String*5, HostName as String*12)
|
||
|
|
||
|
private str8 as string*8
|
||
|
private low as long at str8+4
|
||
|
|
||
|
if CheckPIN(myPIN) <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
' disable admin mode on first use.
|
||
|
if (AdminMode = 1) then
|
||
|
AdminMode = 0
|
||
|
end if
|
||
|
|
||
|
' don't allow operations with default pin
|
||
|
if myPIN = DefaultPIN then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
' Check reader access
|
||
|
if CheckReaderKey(Idx, HOTP) <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
if CheckIndex(Idx) <> 0 then
|
||
|
SW1SW2 = swDataNotFound
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
' when Count32 == 0, use stored count
|
||
|
if Count32 <> 0 then
|
||
|
low = Count32
|
||
|
else
|
||
|
low = HOTPCount32(idx)
|
||
|
end if
|
||
|
|
||
|
call ShaStart()
|
||
|
call ShaAppend(HOTPKeyI(idx))
|
||
|
call ShaAppend(IPAD44)
|
||
|
call ShaAppend(str8)
|
||
|
md1 = ShaEnd()
|
||
|
|
||
|
call ShaStart()
|
||
|
call ShaAppend(HOTPKeyO(idx))
|
||
|
call ShaAppend(OPAD44)
|
||
|
call ShaAppend(md1)
|
||
|
|
||
|
Disable OverflowCheck
|
||
|
HOTPCount32(idx) = low + 1
|
||
|
Enable OverflowCheck
|
||
|
|
||
|
HOTP = left$(ShaEnd(),5)
|
||
|
HostName = HOTPHost(Idx)
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECGETHOTPHOSTCOUNT32
|
||
|
|
||
|
#ifdef ENABLECCLEARALL
|
||
|
command &H80 &H5E ClearAll()
|
||
|
private i,j as Integer
|
||
|
|
||
|
if CheckAdmin() <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
for i = 0 to HOTPNum
|
||
|
|
||
|
HOTPKeyI(i) = Chr$(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
|
||
|
HOTPKeyO(i) = Chr$(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
|
||
|
HOTPCount32(i) = 0
|
||
|
HOTPHost(i) = Chr$(0,0,0,0,0,0,0,0,0,0,0,0)
|
||
|
next i
|
||
|
|
||
|
BalanceCardIndex = 255
|
||
|
|
||
|
PINFailCount = 0
|
||
|
|
||
|
AdminMode = 1
|
||
|
|
||
|
AdminKey = "00000000000000000000"
|
||
|
|
||
|
PIN = DefaultPIN
|
||
|
|
||
|
end command
|
||
|
#endif 'ENABLECCLEARALL
|
||
|
|
||
|
#ifdef ENABLESETREADERKEY
|
||
|
command &H80 &H60 SetReaderKey(myKey as String*5)
|
||
|
|
||
|
if CheckAdmin() <> 0 then
|
||
|
SW1SW2 = swAccessDenied
|
||
|
Exit
|
||
|
end if
|
||
|
|
||
|
readerKey = myKey
|
||
|
|
||
|
end command
|
||
|
|
||
|
#endif 'ENABLECSETREADERKEY
|
||
|
|
||
|
|
||
|
command &H80 &H90 GetCapabilities(C as Long)
|
||
|
|
||
|
C = Capabilities
|
||
|
|
||
|
end command
|
||
|
|
||
|
|