-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtotp_add_command.cpp
82 lines (66 loc) · 2.29 KB
/
totp_add_command.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <string>
#include <exception>
#include <time.h>
#include <math.h>
#include <cctype>
#include <algorithm>
extern "C" {
#include <baseencode.h>
}
#include "totp_command_exception.hpp"
#include "totp_add_command.hpp"
using namespace std;
namespace {
void bin_to_hex(const uint8_t* bin, size_t bin_size, char* hex_out) {
for (size_t i = 0; i < bin_size; i++) {
sprintf(hex_out + 2 * i, "%02x", bin[i]);
}
}
}
TOTP_AddCommand::TOTP_AddCommand(const std::string_view& name, const std::string_view& base32_secret)
: name(name) {
if (name.empty() || base32_secret.empty()) {
throw TOTP_CMD_Exception("invalid argument");
}
secret = std::vector<char>(base32_secret.begin(), base32_secret.end());
std::transform(secret.begin(), secret.end(), secret.begin(), [](unsigned char c) { return std::toupper(c); } );
size_t dst_size = ceil(secret.size() / 1.6);
baseencode_error_t error;
uint8_t* decoded = base32_decode(reinterpret_cast<const char*>(secret.data()), secret.size(), &error);
if (error != SUCCESS) {
throw std::exception();
}
// reuse secret to store the data formatted as hexadecimal string
secret.resize(2 * dst_size + 1, '\0');
bin_to_hex(decoded, dst_size, secret.data());
secret.pop_back(); // remove null terminator from last sprintf
free(decoded);
}
std::vector<char> TOTP_AddCommand::get_cmd() {
vector<char> cmd;
std::string_view header("TOTP_ADD:");
for (auto it = header.begin(); it != header.end(); ++it) {
cmd.push_back(*it);
}
cmd.insert(cmd.end(), name.begin(), name.end());
cmd.push_back(',');
cmd.insert(cmd.end(), secret.begin(), secret.end());
printf("command:\"%s\"\n", std::string(cmd.data(), cmd.size()).c_str());
cmd.push_back('\r');
return cmd;
}
void TOTP_AddCommand::parse_answer(std::list<char> answer) {
string answer_str;
for (auto it = answer.begin(); it != answer.end(); ++it) {
answer_str.push_back(*it);
}
auto found = answer_str.find("TOTP:OK");
if (found != string::npos) {
printf("successfully added OTP key\n");
// TODO: check if result is actually a number
} else {
printf("received: %s\n", answer_str.c_str());
// TODO: throw exception?
}
result.set_value();
}