-
Notifications
You must be signed in to change notification settings - Fork 2
/
kms_client.h
112 lines (91 loc) · 4.43 KB
/
kms_client.h
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#pragma once
#include <base64.h>
#include <http_client.h>
#include <network.h>
#include <switch_security.h>
#include <unordered_map>
class KMSClient final {
private:
uint32_t fault_cnt{0};
HTTPClient http_client;
struct
{
Buffer hostname;
uint16_t port;
} endpoint;
iconv_t iconv_handle;
simple_allocator allocator;
Buffer base64_repr;
Buffer auth_token_base64;
private:
void configure_http_client();
void consider_endpoint_activity(const HTTPClient::request *);
public:
KMSClient(const str_view32 kms_hostname = {"localhost"}, const str_view32 token = {}) {
set_kms_endpoint(kms_hostname);
iconv_handle = iconv_open("utf-8", "iso-8859-7");
if (token)
set_auth_token(token);
configure_http_client();
}
~KMSClient() {
iconv_close(iconv_handle);
}
void set_kms_endpoint(const str_view32 kms_hostname);
void set_auth_token(const str_view32 t) {
auth_token_base64.clear();
//Base64::Encode(reinterpret_cast<const uint8_t *>(t.data()), t.size(), &auth_token_base64);
auth_token_base64.append(t);
}
// input contains pairs of (object id, WRAPPING key)
// KMS will assign the wrapping key to that object id
// See /set_keys
void set(const std::vector<std::pair<str_view8, str_view8>> &input);
// KMS will create the wrapping key for the object
// and will return the wrapping key for each such object
std::unordered_map<str_view8, str_view8> assign(const std::vector<str_view8> &input);
// input contains pairs of (object id, wrapped key)
// KMS will fetch the wrapping key from its persistent secure storage for that object id
// and then unwrap the provided wrapped key to provide us with the unwrapped key
// see /unwrap
std::unordered_map<str_view8, str_view8> unwrap(const std::vector<std::pair<str_view8, str_view8>> &input);
std::unordered_map<str_view8, str_view8> get_keys(const std::vector<str_view8> &);
void erase_keys(const std::vector<str_view8> &);
struct Util {
static void build_iv(const str_view8 objid, uint64_t *iv) {
iv[0] = FNVHash64(reinterpret_cast<const uint8_t *>(objid.data()), objid.size());
iv[1] = XXH64(objid.data(), objid.size(), 1151);
}
static void build_iv(const str_view8 objid, uint8_t *iv) {
// this is purely a convention
// for simplicity reasons, ivs will always be derived from the object id
build_iv(objid, reinterpret_cast<uint64_t *>(iv));
}
// this is handy
// you can e.g use
// objdata_enc_proxy enc_proxy("bp/users/54"_su8, key_from_ms);
// const auto email_ciphertext = enc_proxy.encrypt(row[10])
struct objdata_enc_proxy {
uint64_t iv[2];
uint8_t key[32];
objdata_enc_proxy(const str_view8 objid, const uint8_t obj_data_key[32]) {
build_iv(objid, iv);
memcpy(key, obj_data_key, 32); // AES-256
}
auto encrypt(const str_view32 plaintext) const {
return switch_security::ciphers::aes256{{key, 32}, {reinterpret_cast<const uint8_t *>(iv), 16}}.encrypt(plaintext);
}
};
struct objdata_dec_proxy {
uint64_t iv[2];
uint8_t key[32];
objdata_dec_proxy(const str_view8 objid, const uint8_t obj_data_key[32]) {
build_iv(objid, iv);
memcpy(key, obj_data_key, 32); // AES-256
}
auto decrypt(const str_view32 ciphertext) const {
return ciphertext ? switch_security::ciphers::aes256{{key, 32}, {reinterpret_cast<const uint8_t *>(iv), 16}}.decrypt(ciphertext) : Buffer();
}
};
};
};