cryptutils

Cryptographic Software Utilities
git clone http://git.omkov.net/cryptutils
Log | Tree | Refs | README | LICENCE | Download

cryptutils/src/otp.c (95 lines, 2.6 KiB) -rw-r--r-- file download

3275b9a Jamozed 2021-02-21 23:43:50
0
// otp.c, version 0.2.0
79268b0 Jamozed 2021-01-23 21:37:30
1
// OMKOV cryptutils otp
79268b0 Jamozed 2021-01-23 21:37:30
2
// Copyright (C) 2020, Jakob Wakeling
45f70e3 Jamozed 2022-03-06 17:15:30
3
// MIT Licence
79268b0 Jamozed 2021-01-23 21:37:30
4
c01a723 Jamozed 2022-02-05 19:04:03
5
#include "util/base32.h"
c01a723 Jamozed 2022-02-05 19:04:03
6
#include "util/error.c"
c01a723 Jamozed 2022-02-05 19:04:03
7
#include "util/optget.h"
c01a723 Jamozed 2022-02-05 19:04:03
8
#include "util/strconv.h"
79268b0 Jamozed 2021-01-23 21:37:30
9
79268b0 Jamozed 2021-01-23 21:37:30
10
#include <openssl/evp.h>
79268b0 Jamozed 2021-01-23 21:37:30
11
#include <openssl/hmac.h>
79268b0 Jamozed 2021-01-23 21:37:30
12
79268b0 Jamozed 2021-01-23 21:37:30
13
#include <math.h>
79268b0 Jamozed 2021-01-23 21:37:30
14
#include <stdint.h>
79268b0 Jamozed 2021-01-23 21:37:30
15
#include <stdio.h>
79268b0 Jamozed 2021-01-23 21:37:30
16
3275b9a Jamozed 2021-02-21 23:43:50
17
#define VERSION "0.2.0"
79268b0 Jamozed 2021-01-23 21:37:30
18
79268b0 Jamozed 2021-01-23 21:37:30
19
static struct lop lops[] = {
79268b0 Jamozed 2021-01-23 21:37:30
20
	{ "help",    ARG_NUL, 256 },
79268b0 Jamozed 2021-01-23 21:37:30
21
	{ "version", ARG_NUL, 257 },
79268b0 Jamozed 2021-01-23 21:37:30
22
	{ NULL, 0, 0 }
79268b0 Jamozed 2021-01-23 21:37:30
23
};
79268b0 Jamozed 2021-01-23 21:37:30
24
79268b0 Jamozed 2021-01-23 21:37:30
25
static inline uint32_t hotp(uint8_t *K, size_t Klen, uint64_t C);
79268b0 Jamozed 2021-01-23 21:37:30
26
79268b0 Jamozed 2021-01-23 21:37:30
27
static void hlp(void);
79268b0 Jamozed 2021-01-23 21:37:30
28
static void ver(void);
79268b0 Jamozed 2021-01-23 21:37:30
29
79268b0 Jamozed 2021-01-23 21:37:30
30
int main(int ac, char *av[]) { A0 = av[0];
79268b0 Jamozed 2021-01-23 21:37:30
31
	struct opt opt = OPTGET_INIT; opt.str = ""; opt.lops = lops;
79268b0 Jamozed 2021-01-23 21:37:30
32
	for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) {
79268b0 Jamozed 2021-01-23 21:37:30
33
	case 256: { hlp(); return 0; }
79268b0 Jamozed 2021-01-23 21:37:30
34
	case 257: { ver(); return 0; }
79268b0 Jamozed 2021-01-23 21:37:30
35
	default: { return 1; }
79268b0 Jamozed 2021-01-23 21:37:30
36
	}
79268b0 Jamozed 2021-01-23 21:37:30
37
	
79268b0 Jamozed 2021-01-23 21:37:30
38
	if (opt.ind == ac) { error(1, "missing operand"); }
79268b0 Jamozed 2021-01-23 21:37:30
39
	
79268b0 Jamozed 2021-01-23 21:37:30
40
	uint8_t *k; size_t l = strlen(av[opt.ind]); uint64_t c;
79268b0 Jamozed 2021-01-23 21:37:30
41
	
79268b0 Jamozed 2021-01-23 21:37:30
42
	if (opt.ind == ac - 1) { c = time(NULL) / 30; }
79268b0 Jamozed 2021-01-23 21:37:30
43
	else {
3275b9a Jamozed 2021-02-21 23:43:50
44
		char *ep; c = strtou64(av[opt.ind + 1], &ep, 10);
3275b9a Jamozed 2021-02-21 23:43:50
45
		if (*ep) { error(1, "invalid counter"); }
79268b0 Jamozed 2021-01-23 21:37:30
46
	}
79268b0 Jamozed 2021-01-23 21:37:30
47
	
3275b9a Jamozed 2021-02-21 23:43:50
48
	k = (uint8_t *)malloc(B32DLEN(l) * sizeof (*k));
3275b9a Jamozed 2021-02-21 23:43:50
49
	if (!k) { error(1, "%s", serr()); }
3275b9a Jamozed 2021-02-21 23:43:50
50
	
3275b9a Jamozed 2021-02-21 23:43:50
51
	size_t kl = b32decode(k, (uint8_t *)av[opt.ind], l);
3275b9a Jamozed 2021-02-21 23:43:50
52
	
3275b9a Jamozed 2021-02-21 23:43:50
53
	printf("%06u\n", hotp(k, kl, c)); free(k); return 0;
79268b0 Jamozed 2021-01-23 21:37:30
54
}
79268b0 Jamozed 2021-01-23 21:37:30
55
79268b0 Jamozed 2021-01-23 21:37:30
56
/* Compute HOTP token with a key and counter */
79268b0 Jamozed 2021-01-23 21:37:30
57
static inline uint32_t hotp(uint8_t *K, size_t Klen, uint64_t C) {
79268b0 Jamozed 2021-01-23 21:37:30
58
	// Convert the counter to big endian if it isn't already
79268b0 Jamozed 2021-01-23 21:37:30
59
	uint32_t e = 0x000000FF; if ((*(uint8_t *)&e) == 0xFF) {
79268b0 Jamozed 2021-01-23 21:37:30
60
		C = ((C & 0x00000000FFFFFFFF) << 32) | ((C & 0xFFFFFFFF00000000) >> 32);
79268b0 Jamozed 2021-01-23 21:37:30
61
		C = ((C & 0x0000FFFF0000FFFF) << 16) | ((C & 0xFFFF0000FFFF0000) >> 16);
79268b0 Jamozed 2021-01-23 21:37:30
62
		C = ((C & 0x00FF00FF00FF00FF) <<  8) | ((C & 0xFF00FF00FF00FF00) >>  8);
79268b0 Jamozed 2021-01-23 21:37:30
63
	}
79268b0 Jamozed 2021-01-23 21:37:30
64
	
79268b0 Jamozed 2021-01-23 21:37:30
65
	// Step 1: Generate HMAC-SHA-1 digest
79268b0 Jamozed 2021-01-23 21:37:30
66
	uint8_t *d = HMAC(EVP_sha1(), K, Klen, (uint8_t *)&C, sizeof (C), NULL, 0);
79268b0 Jamozed 2021-01-23 21:37:30
67
	
79268b0 Jamozed 2021-01-23 21:37:30
68
	// Step 2: Truncate digest to 4 bytes
79268b0 Jamozed 2021-01-23 21:37:30
69
	uint32_t dt =
79268b0 Jamozed 2021-01-23 21:37:30
70
		(d[(d[19] & 0x0F)]     & 0x7F) << 24 |
79268b0 Jamozed 2021-01-23 21:37:30
71
		(d[(d[19] & 0x0F) + 1] & 0xFF) << 16 |
79268b0 Jamozed 2021-01-23 21:37:30
72
		(d[(d[19] & 0x0F) + 2] & 0xFF) << 8  |
79268b0 Jamozed 2021-01-23 21:37:30
73
		(d[(d[19] & 0x0F) + 3] & 0xFF);
79268b0 Jamozed 2021-01-23 21:37:30
74
	
79268b0 Jamozed 2021-01-23 21:37:30
75
	// Step 3: Calculate modulus of dt to get HOTP token
79268b0 Jamozed 2021-01-23 21:37:30
76
	return dt % (uint32_t)pow(10, 6/*Token length*/);
79268b0 Jamozed 2021-01-23 21:37:30
77
}
79268b0 Jamozed 2021-01-23 21:37:30
78
79268b0 Jamozed 2021-01-23 21:37:30
79
/* Print help information */
79268b0 Jamozed 2021-01-23 21:37:30
80
static void hlp(void) {
79268b0 Jamozed 2021-01-23 21:37:30
81
	puts("otp - compute hotp or totp tokens\n");
79268b0 Jamozed 2021-01-23 21:37:30
82
	puts("usage: otp secret [counter]\n");
79268b0 Jamozed 2021-01-23 21:37:30
83
	puts("options:");
79268b0 Jamozed 2021-01-23 21:37:30
84
	puts("  --help     Display help information");
79268b0 Jamozed 2021-01-23 21:37:30
85
	puts("  --version  Display version information");
79268b0 Jamozed 2021-01-23 21:37:30
86
}
79268b0 Jamozed 2021-01-23 21:37:30
87
79268b0 Jamozed 2021-01-23 21:37:30
88
/* Print version information */
79268b0 Jamozed 2021-01-23 21:37:30
89
static void ver(void) {
79268b0 Jamozed 2021-01-23 21:37:30
90
	puts("OMKOV cryptutils otp, version " VERSION);
79268b0 Jamozed 2021-01-23 21:37:30
91
	puts("Copyright (C) 2020, Jakob Wakeling");
45f70e3 Jamozed 2022-03-06 17:15:30
92
	puts("MIT Licence (https://opensource.org/licenses/MIT)");
79268b0 Jamozed 2021-01-23 21:37:30
93
}
94