|
|
|
@ -18,19 +18,47 @@
|
|
|
|
|
|
|
|
|
|
#include "otp.h" |
|
|
|
|
|
|
|
|
|
static int32_t |
|
|
|
|
otp(const EVP_MD *evp_md, const void *key, int key_len, uint64_t counter, |
|
|
|
|
unsigned int digits) |
|
|
|
|
int32_t |
|
|
|
|
otp(const struct otpcfg *otpcfg) |
|
|
|
|
{ |
|
|
|
|
const EVP_MD *evp_md; |
|
|
|
|
unsigned char md_value[EVP_MAX_MD_SIZE]; |
|
|
|
|
uint8_t buf[8]; |
|
|
|
|
uint64_t counter; |
|
|
|
|
uint32_t res; |
|
|
|
|
int32_t modulo; |
|
|
|
|
unsigned int md_len, offset; |
|
|
|
|
unsigned int digits, md_len, offset; |
|
|
|
|
|
|
|
|
|
if (digits < 6 || digits > 10) |
|
|
|
|
switch (otpcfg->type) { |
|
|
|
|
case OTP_HOTP: |
|
|
|
|
counter = otpcfg->u.hotp.counter; |
|
|
|
|
break; |
|
|
|
|
case OTP_TOTP: |
|
|
|
|
if (otpcfg->u.totp.period == 0) |
|
|
|
|
return -1; |
|
|
|
|
counter = otpcfg->u.totp.time / otpcfg->u.totp.period; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
switch (otpcfg->algorithm) { |
|
|
|
|
case OTP_HMAC_SHA1: |
|
|
|
|
evp_md = EVP_sha1(); |
|
|
|
|
break; |
|
|
|
|
case OTP_HMAC_SHA256: |
|
|
|
|
evp_md = EVP_sha256(); |
|
|
|
|
break; |
|
|
|
|
case OTP_HMAC_SHA512: |
|
|
|
|
evp_md = EVP_sha512(); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
digits = otpcfg->digits; |
|
|
|
|
if (digits < 6 || digits > 10) |
|
|
|
|
return -1; |
|
|
|
|
/*
|
|
|
|
|
* 10 digits would be 10_000_000_000, which overflows 32 bits. |
|
|
|
|
* Nevertheless, given the number construction, 10 digits OTP are |
|
|
|
@ -50,8 +78,8 @@ otp(const EVP_MD *evp_md, const void *key, int key_len, uint64_t counter,
|
|
|
|
|
buf[6] = (counter >> 8) & 0xff; |
|
|
|
|
buf[7] = counter & 0xff; |
|
|
|
|
|
|
|
|
|
if (HMAC(evp_md, key, key_len, buf, sizeof(buf), md_value, &md_len) == |
|
|
|
|
NULL) |
|
|
|
|
if (HMAC(evp_md, otpcfg->secret, otpcfg->secretlen, buf, sizeof(buf), |
|
|
|
|
md_value, &md_len) == NULL) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
offset = md_value[md_len - 1] & 0xf; |
|
|
|
@ -63,36 +91,3 @@ otp(const EVP_MD *evp_md, const void *key, int key_len, uint64_t counter,
|
|
|
|
|
|
|
|
|
|
return digits == 10 ? (int32_t)res : (int32_t)res % modulo; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int32_t |
|
|
|
|
hotp(enum otp_hmac hmac, const void *key, size_t key_len, uint64_t counter, |
|
|
|
|
unsigned int digits) |
|
|
|
|
{ |
|
|
|
|
const EVP_MD *evp_md; |
|
|
|
|
|
|
|
|
|
if (key_len > INT_MAX) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
switch (hmac) { |
|
|
|
|
case OTP_HMAC_SHA1: |
|
|
|
|
evp_md = EVP_sha1(); |
|
|
|
|
break; |
|
|
|
|
case OTP_HMAC_SHA256: |
|
|
|
|
evp_md = EVP_sha256(); |
|
|
|
|
break; |
|
|
|
|
case OTP_HMAC_SHA512: |
|
|
|
|
evp_md = EVP_sha512(); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return otp(evp_md, key, (int)key_len, counter, digits); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int32_t |
|
|
|
|
totp(enum otp_hmac hmac, const void *key, size_t key_len, uint64_t t, |
|
|
|
|
unsigned int period, unsigned int digits) |
|
|
|
|
{ |
|
|
|
|
return hotp(hmac, key, key_len, t / period, digits); |
|
|
|
|
} |
|
|
|
|