totp

Simple cli tool for storing TOTP secrets and generating tokens
git clone https://git.inz.fi/totp/
Log | Files | Refs | Submodules

commit 4c3b80f9966566ed49e36da09cfd2862e6ceac6c
parent cd5ae858029fe0aa7d53759aff4bcf661ac542cf
Author: Santtu Lakkala <inz@inz.fi>
Date:   Tue, 18 May 2021 00:15:08 +0300

Add missing files

Diffstat:
Autil.c | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Autil.h | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 229 insertions(+), 0 deletions(-)

diff --git a/util.c b/util.c @@ -0,0 +1,148 @@ +#include <stdint.h> +#include <string.h> +#include <stdarg.h> +#include <stdio.h> +#include <arpa/inet.h> + +#include "util.h" + +void xormem(void *a, const void *b, size_t len) +{ + uint8_t *wa = a; + const uint8_t *rb = b; + while (len--) + *wa++ ^= *rb++; +} + +void hmac(const void *key, size_t keylen, + const void *data, size_t datalen, + digest_init init, + digest_update update, + digest_finish finish, + size_t ctxsz, + size_t blocksz, + size_t digestsz, + ptrdiff_t buf_off, + ptrdiff_t digest_off, + void *h) +{ + char s[ctxsz]; + char s2[ctxsz]; + + init(s); + memset(s + buf_off, 0x36, blocksz); + if (keylen > blocksz) { + init(s2); + update(s2, key, keylen); + finish(s2); + xormem(s + buf_off, s2 + digest_off, digestsz); + } else { + xormem(s + buf_off, key, keylen); + } + + update(s, s + buf_off, blocksz); + update(s, data, datalen); + finish(s); + + memset(s2 + buf_off, 0x5c, blocksz); + if (keylen > blocksz) + xormem(s2 + buf_off, s2 + digest_off, digestsz); + else + xormem(s2 + buf_off, key, keylen); + init(s2); + update(s2, s2 + buf_off, blocksz); + update(s2, s + digest_off, digestsz); + finish(s2); + memcpy(h, s2 + digest_off, digestsz); +} + +uint32_t hotp(const void *key, size_t keylen, + const void *counter, size_t counterlen, + void (*hmac_f)(const void *key, size_t keylen, + const void *data, size_t datalen, + void *h), size_t hshsz) +{ + uint8_t h[hshsz]; + + hmac_f(key, keylen, counter, counterlen, h); + + return ntohl(*(uint32_t *)&((uint8_t *)h)[h[hshsz - 1] & 0xf]) & + 0x7fffffff; +} + +uint32_t totp(const void *key, size_t keylen, + time_t t1, uint8_t period, + time_t t0, + void (*hmac_f)(const void *key, size_t keylen, + const void *data, size_t datalen, + void *h), size_t hshsz) +{ + uint64_t tv = _htonll((t1 - t0) / period); + + return hotp(key, keylen, &tv, sizeof(tv), hmac_f, hshsz); +} + +size_t strncspn(const char *s, size_t l, const char *c) +{ + size_t disallowed[256 / 8 / sizeof(size_t)] = { 0 }; + const unsigned char *u = (const unsigned char *)c; + + if (!*c) + return 0; + for (u = (const unsigned char *)c; + *u && (disallowed[*u / (8 * sizeof(*disallowed))] |= 1ULL << (*u % (8 * sizeof(*disallowed)))); + u++); + disallowed[0] |= 1; + for (u = (const unsigned char *)s; + l-- && !(disallowed[*u / (8 * sizeof(*disallowed))] & 1ULL << (*u % (8 * sizeof(*disallowed)))); + u++); + + return (const char *)u - s; +} + +size_t strnspn(const char *s, size_t l, const char *c) +{ + size_t allowed[256 / 8 / sizeof(size_t)] = { 0 }; + const unsigned char *u = (const unsigned char *)c; + + if (!*c) + return 0; + for (u = (const unsigned char *)c; + *u && (allowed[*u / (8 * sizeof(*allowed))] |= 1ULL << (*u % (8 * sizeof(*allowed)))); + u++); + for (u = (const unsigned char *)s; + l-- && (allowed[*u / (8 * sizeof(*allowed))] & 1ULL << (*u % (8 * sizeof(*allowed)))); + u++); + + return (const char *)u - s; +} + +void croak(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fputs("\n", stderr); + + exit(1); +} + +size_t debase32(char *buffer, size_t len) +{ + uint8_t *wp = (uint8_t *)buffer; + const uint8_t *rp = (const uint8_t *)buffer; + uint16_t v = 0; + size_t b = 0; + + for (rp = (uint8_t *)buffer; (char *)rp - buffer < (ptrdiff_t)len && *rp && *rp != '='; rp++) { + uint8_t c = *rp >= 'A' ? *rp - 'A' : *rp - '2' + 26; + v = v << 5 | c; + b += 5; + if (b >= 8) { + *wp++ = (v >> (b & 7)) & 255; + b -= 8; + } + } + return (char *)wp - buffer; +} diff --git a/util.h b/util.h @@ -0,0 +1,81 @@ +#ifndef UTIL_H +#define UTIL_H + +#include <stdlib.h> +#include <stddef.h> +#include <stdint.h> +#include <time.h> + +#include <arpa/inet.h> + +typedef void (*digest_init)(void *c); +typedef void (*digest_update)(void *c, const void *data, size_t len); +typedef void (*digest_finish)(void *c); + +void xormem(void *a, const void *b, size_t len); +void hmac(const void *key, size_t keylen, + const void *data, size_t datalen, + digest_init init, + digest_update update, + digest_finish finish, + size_t ctxsz, + size_t blocksz, + size_t digestsz, + ptrdiff_t buf_off, + ptrdiff_t digest_off, + void *h); + +uint32_t totp(const void *key, size_t keylen, + time_t t1, uint8_t period, + time_t t0, + void (*hmac_f)(const void *key, size_t keylen, + const void *data, size_t datalen, + void *h), size_t hshsz); + +uint32_t hotp(const void *key, size_t keylen, + const void *counter, size_t counterlen, + void (*hmac_f)(const void *key, size_t keylen, + const void *data, size_t datalen, + void *h), size_t hshsz); + +size_t strncspn(const char *haystack, size_t haystacklen, const char *needles); + +static inline uint64_t _htonll(uint64_t v) +{ + union { + uint64_t v64; + uint32_t v32[2]; + } rv; + rv.v32[0] = htonl(v >> 32); + rv.v32[1] = htonl(v & 0xffffffffU); + + return rv.v64; +} + +static inline uint64_t _ntohll(uint64_t v) +{ + union { + uint64_t v64; + uint32_t v32[2]; + } rv; + rv.v64 = v; + + return (uint64_t)ntohl(rv.v32[0]) << 32 | ntohl(rv.v32[1]); +} + +static inline void writebeu64(uint8_t *buffer, uint64_t v) +{ + *buffer++ = v >> 56; + *buffer++ = v >> 48; + *buffer++ = v >> 40; + *buffer++ = v >> 32; + *buffer++ = v >> 24; + *buffer++ = v >> 16; + *buffer++ = v >> 8; + *buffer++ = v; +} + +void croak(const char *fmt, ...); +size_t debase32(char *buffer, size_t len); + +#endif