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
|
|