yms/libotp.php
author Dan Fuhry <dan@enanocms.org>
Wed, 11 Jan 2017 13:02:34 +0000
changeset 12 31387f4022e5
parent 0 9997bee9ad03
permissions -rw-r--r--
Tolerate up to 0.5Hz difference in OTP timestamps I've received complaints of OTP validation failures during the trial rollout at Datto. I dumped a few OTPs along with the times of validation and found that the user's Yubikey was running its oscillator at 8.32Hz. This commit adds tolerance for up to 0.5Hz of variation to the OTP's timestamp field.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
     1
<?php
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
     2
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
     3
/**
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
     4
 * Returns OTP data. Numeric except for public and private IDs, which are hex.
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
     5
 * @return array Associative
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
     6
 */
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
     7
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
     8
function yms_decode_otp($otp, $key)
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
     9
{
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    10
  static $aes = false;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    11
  if ( !is_object($aes) )
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    12
    $aes = AESCrypt::singleton(128, 128);
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    13
  
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    14
  $return = array();
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    15
  
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    16
  $otp = yms_tobinary($otp);
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    17
  if ( strlen($otp) != 22 )
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    18
  {
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    19
    return false;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    20
  }
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    21
  $key = yms_tobinary($key);
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    22
  if ( strlen($key) != 16 )
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    23
  {
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    24
    return false;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    25
  }
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    26
  
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    27
  $cryptpart = yms_hex_encode(substr($otp, 6, 16));
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    28
  $publicid = substr($otp, 0, 6);
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    29
  
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    30
  $return['publicid'] = yms_hex_encode($publicid);
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    31
  $otp_decrypted = $aes->decrypt($cryptpart, $key, ENC_HEX);
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    32
  $crc_is_good = yms_validate_crc($otp_decrypted);
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    33
  $return['privateid'] = yms_hex_encode(substr($otp_decrypted, 0, 6));
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    34
  $return['session'] = yms_unpack_int(strrev(substr($otp_decrypted, 6, 2)));
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    35
  $return['timestamp'] = yms_unpack_int(strrev(substr($otp_decrypted, 8, 3)));
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    36
  $return['count'] = yms_unpack_int(substr($otp_decrypted, 11, 1));
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    37
  $return['random'] = yms_unpack_int(substr($otp_decrypted, 12, 2));
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    38
  $return['crc'] = yms_unpack_int(substr($otp_decrypted, 14, 2));
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    39
  $return['crc_good'] = $crc_is_good;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    40
  
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    41
  return $return;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    42
}
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    43
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    44
function yms_unpack_int($str)
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    45
{
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    46
  $return = 0;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    47
  for ( $i = 0; $i < strlen($str); $i++ )
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    48
  {
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    49
    $return = $return << 8;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    50
    $return = $return | ord($str{$i});
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    51
  }
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    52
  return $return;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    53
}
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    54
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    55
function yms_crc16($buffer)
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    56
{
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    57
  $buffer = yms_tobinary($buffer);
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    58
  
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    59
  $m_crc=0x5af0;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    60
  for($bpos=0; $bpos<strlen($buffer); $bpos++)
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    61
  {
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    62
    $m_crc ^= ord($buffer[$bpos]);
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    63
    for ($i=0; $i<8; $i++)
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    64
    {
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    65
      $j=$m_crc & 1;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    66
      $m_crc >>= 1;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    67
      if ($j) $m_crc ^= 0x8408;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    68
    }
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    69
  }
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    70
  return $m_crc;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    71
}
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    72
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    73
function yms_validate_crc($token)
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    74
{
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    75
  $crc = yms_crc16($token);
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    76
  return $crc == 0;
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    77
}
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    78
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    79
function yms_within($test, $control, $fuzz)
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    80
{
12
31387f4022e5 Tolerate up to 0.5Hz difference in OTP timestamps
Dan Fuhry <dan@enanocms.org>
parents: 0
diff changeset
    81
  return abs($control - $test) <= $fuzz;
0
9997bee9ad03 First commit. Lacks key deletion support and an admin CP for controlling options.
Dan
parents:
diff changeset
    82
}