Add HOTP implementation

This commit is contained in:
Lucas 2020-06-14 04:02:13 +00:00
parent 46dd62038f
commit a28d7cca02
3 changed files with 111 additions and 2 deletions

View File

@ -17,8 +17,8 @@
P = otpcli
V = 0.0
HDR = err.h
OBJ = cli.o err.o
HDR = err.h otp.h
OBJ = cli.o err.o otp.o
SRC = ${OBJ:.o=.c}
DIST_FILES = COPYING Makefile ${HDR} ${SRC}

82
otp.c Normal file
View File

@ -0,0 +1,82 @@
/*
* otpcli - CLI utility for generating OTPs
*
* Written in 2020 by Lucas
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <limits.h>
#include <openssl/hmac.h>
#include "otp.h"
static int32_t
otp(const EVP_MD *evp_md, const void *key, int key_len, uint64_t counter,
unsigned int digits)
{
unsigned char md_value[EVP_MAX_MD_SIZE];
uint8_t buf[8];
uint32_t res;
unsigned int md_len, modulo, offset;
if (digits < 6 || digits > 10)
return -1;
for (modulo = 1000000; digits > 6; digits--, modulo *= 10)
;
/* convert counter to big endian */
buf[0] = counter >> 56;
buf[1] = (counter >> 48) & 0xff;
buf[2] = (counter >> 40) & 0xff;
buf[3] = (counter >> 32) & 0xff;
buf[4] = (counter >> 24) & 0xff;
buf[5] = (counter >> 16) & 0xff;
buf[6] = (counter >> 8) & 0xff;
buf[7] = counter & 0xff;
if (HMAC(evp_md, key, key_len, buf, sizeof(buf), md_value, &md_len) ==
NULL)
return -1;
offset = md_value[md_len - 1] & 0xf;
res = (md_value[offset] << 24) |
(md_value[offset + 1] << 16) |
(md_value[offset + 2] << 8) |
md_value[offset + 3];
res &= ~0x80000000;
return (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;
}
return otp(evp_md, key, (int)key_len, counter, digits);
}
int32_t
totp(enum otp_hmac hmac, const void *key, size_t key_len, time_t t,
unsigned int granularity, unsigned int digits)
{
return -1;
}

27
otp.h Normal file
View File

@ -0,0 +1,27 @@
/*
* otpcli - CLI utility for generating OTPs
*
* Written in 2020 by Lucas
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdint.h>
#include <time.h>
enum otp_hmac {
OTP_HMAC_SHA1,
OTP_HMAC_SHA256,
OTP_HMAC_SHA512,
};
int32_t hotp(enum otp_hmac, const void *, size_t, uint64_t, unsigned int);
int32_t totp(enum otp_hmac, const void *, size_t, time_t, unsigned int,
unsigned int);