CDC Badge OS
Firmware for the CDC Badge v1.0 hardware security key
Loading...
Searching...
No Matches
kdf.cpp
Go to the documentation of this file.
1
4
6#include <string.h>
7
9 if (out) memset(out, 0, sizeof(*out));
10}
11
13static bool valid_hash(uint8_t h) {
14 return h == KDF_HASH_NONE || h == KDF_HASH_SHA256 || h == KDF_HASH_SHA512;
15}
16
18static bool emit_tlv(uint8_t* out, size_t cap, size_t* pos, uint8_t tag,
19 const uint8_t* v, uint8_t l) {
20 if (*pos + 2u + l > cap) return false;
21 out[(*pos)++] = tag;
22 out[(*pos)++] = l;
23 memcpy(out + *pos, v, l);
24 *pos += l;
25 return true;
26}
27
28kdf_status_t kdf_do_parse(const uint8_t* bytes, size_t len, kdf_do_t* out) {
29 if (!bytes || !out) return KDF_ERR_NULL;
30 kdf_do_clear(out);
31
32 size_t pos = 0;
33 while (pos < len) {
34 if (pos + 2 > len) return KDF_ERR_BAD_LENGTH;
35 const uint8_t tag = bytes[pos++];
36 const uint8_t l = bytes[pos++];
37 if (pos + l > len) return KDF_ERR_BAD_LENGTH;
38 const uint8_t* v = bytes + pos;
39 pos += l;
40
41 switch (tag) {
42 case 0x81:
43 if (l != 1) return KDF_ERR_BAD_LENGTH;
44 if (v[0] != KDF_ALGO_NONE && v[0] != KDF_ALGO_PBKDF2) return KDF_ERR_BAD_ALGO;
45 out->algo = static_cast<kdf_algo_t>(v[0]);
46 break;
47 case 0x82:
48 if (l != 1) return KDF_ERR_BAD_LENGTH;
49 if (!valid_hash(v[0])) return KDF_ERR_BAD_HASH;
50 out->hash = static_cast<kdf_hash_t>(v[0]);
51 break;
52 case 0x83:
53 if (l != 4) return KDF_ERR_BAD_LENGTH;
54 out->iter_count = (static_cast<uint32_t>(v[0]) << 24) |
55 (static_cast<uint32_t>(v[1]) << 16) |
56 (static_cast<uint32_t>(v[2]) << 8) |
57 static_cast<uint32_t>(v[3]);
58 break;
59 case 0x84:
60 if (l != KDF_SALT_LEN) return KDF_ERR_BAD_LENGTH;
61 memcpy(out->pw1_salt, v, KDF_SALT_LEN);
62 out->has_pw1_salt = true;
63 break;
64 case 0x85:
65 if (l != KDF_SALT_LEN) return KDF_ERR_BAD_LENGTH;
66 memcpy(out->rc_salt, v, KDF_SALT_LEN);
67 out->has_rc_salt = true;
68 break;
69 case 0x86:
70 if (l != KDF_SALT_LEN) return KDF_ERR_BAD_LENGTH;
71 memcpy(out->pw3_salt, v, KDF_SALT_LEN);
72 out->has_pw3_salt = true;
73 break;
74 case 0x87:
75 if (l != 32 && l != 64) return KDF_ERR_BAD_HASH_LEN;
76 memcpy(out->pw1_initial, v, l);
77 out->pw1_initial_len = l;
78 out->has_pw1_initial = true;
79 break;
80 case 0x88:
81 if (l != 32 && l != 64) return KDF_ERR_BAD_HASH_LEN;
82 memcpy(out->pw3_initial, v, l);
83 out->pw3_initial_len = l;
84 out->has_pw3_initial = true;
85 break;
86 default:
87 return KDF_ERR_BAD_TAG;
88 }
89 }
90 return KDF_OK;
91}
92
93kdf_status_t kdf_do_build(const kdf_do_t* kdf, uint8_t* out, size_t out_cap, size_t* out_len) {
94 if (!kdf || !out || !out_len) return KDF_ERR_NULL;
95 size_t pos = 0;
96 const uint8_t algo = static_cast<uint8_t>(kdf->algo);
97 const uint8_t hash = static_cast<uint8_t>(kdf->hash);
98 if (!emit_tlv(out, out_cap, &pos, 0x81, &algo, 1)) return KDF_ERR_BUF_TOO_SMALL;
99 if (!emit_tlv(out, out_cap, &pos, 0x82, &hash, 1)) return KDF_ERR_BUF_TOO_SMALL;
100
101 if (kdf->algo == KDF_ALGO_PBKDF2) {
102 const uint8_t it[4] = {
103 static_cast<uint8_t>((kdf->iter_count >> 24) & 0xFF),
104 static_cast<uint8_t>((kdf->iter_count >> 16) & 0xFF),
105 static_cast<uint8_t>((kdf->iter_count >> 8) & 0xFF),
106 static_cast<uint8_t>(kdf->iter_count & 0xFF),
107 };
108 if (!emit_tlv(out, out_cap, &pos, 0x83, it, 4)) return KDF_ERR_BUF_TOO_SMALL;
109 if (kdf->has_pw1_salt && !emit_tlv(out, out_cap, &pos, 0x84, kdf->pw1_salt, KDF_SALT_LEN))
111 if (kdf->has_rc_salt && !emit_tlv(out, out_cap, &pos, 0x85, kdf->rc_salt, KDF_SALT_LEN))
113 if (kdf->has_pw3_salt && !emit_tlv(out, out_cap, &pos, 0x86, kdf->pw3_salt, KDF_SALT_LEN))
115 if (kdf->has_pw1_initial &&
116 !emit_tlv(out, out_cap, &pos, 0x87, kdf->pw1_initial, kdf->pw1_initial_len))
118 if (kdf->has_pw3_initial &&
119 !emit_tlv(out, out_cap, &pos, 0x88, kdf->pw3_initial, kdf->pw3_initial_len))
121 }
122 *out_len = pos;
123 return KDF_OK;
124}
125
126kdf_status_t kdf_do_build_disabled(uint8_t* out, size_t out_cap, size_t* out_len) {
127 if (!out || !out_len) return KDF_ERR_NULL;
128 if (out_cap < 3) return KDF_ERR_BUF_TOO_SMALL;
129 out[0] = 0x81;
130 out[1] = 0x01;
131 out[2] = KDF_ALGO_NONE;
132 *out_len = 3;
133 return KDF_OK;
134}
static bool valid_hash(uint8_t h)
Accepts the hash identifiers the codec understands.
Definition kdf.cpp:13
kdf_status_t kdf_do_parse(const uint8_t *bytes, size_t len, kdf_do_t *out)
Parse a KDF-DO byte sequence into structured form.
Definition kdf.cpp:28
kdf_status_t kdf_do_build_disabled(uint8_t *out, size_t out_cap, size_t *out_len)
Convenience helper: produce the "KDF disabled" KDF-DO body — three bytes (81 01 00) — that hosts expe...
Definition kdf.cpp:126
kdf_status_t kdf_do_build(const kdf_do_t *kdf, uint8_t *out, size_t out_cap, size_t *out_len)
Serialise a kdf_do_t into the wire byte sequence.
Definition kdf.cpp:93
void kdf_do_clear(kdf_do_t *out)
OpenPGP KDF Data Object (tag F9) byte codec (see kdf.h).
Definition kdf.cpp:8
static bool emit_tlv(uint8_t *out, size_t cap, size_t *pos, uint8_t tag, const uint8_t *v, uint8_t l)
Emits a single 1-byte-length inner TLV; returns false on overflow.
Definition kdf.cpp:18
#define KDF_SALT_LEN
OpenPGP KDF Data Object (tag F9) byte codec.
Definition kdf.h:34
kdf_hash_t
Hash algorithms accepted inside KDF-DO (inner tag 0x82).
Definition kdf.h:44
@ KDF_HASH_NONE
Definition kdf.h:45
@ KDF_HASH_SHA256
Definition kdf.h:46
@ KDF_HASH_SHA512
Definition kdf.h:47
kdf_algo_t
KDF algorithm identifiers (DO 0xF9 inner tag 0x81).
Definition kdf.h:38
@ KDF_ALGO_NONE
Definition kdf.h:39
@ KDF_ALGO_PBKDF2
Definition kdf.h:40
kdf_status_t
KDF-DO codec error codes.
Definition kdf.h:72
@ KDF_OK
Definition kdf.h:73
@ KDF_ERR_BAD_ALGO
Definition kdf.h:78
@ KDF_ERR_BAD_LENGTH
Definition kdf.h:76
@ KDF_ERR_NULL
Definition kdf.h:74
@ KDF_ERR_BUF_TOO_SMALL
Definition kdf.h:75
@ KDF_ERR_BAD_HASH
Definition kdf.h:79
@ KDF_ERR_BAD_TAG
Definition kdf.h:77
@ KDF_ERR_BAD_HASH_LEN
Definition kdf.h:80
Parsed KDF-DO contents.
Definition kdf.h:51
kdf_algo_t algo
Definition kdf.h:52
uint8_t rc_salt[8]
Definition kdf.h:59
uint8_t pw3_initial_len
Definition kdf.h:68
uint8_t pw3_initial[64]
Definition kdf.h:67
bool has_rc_salt
Definition kdf.h:58
uint8_t pw1_initial_len
Definition kdf.h:65
uint8_t pw1_salt[8]
Definition kdf.h:57
bool has_pw3_initial
Definition kdf.h:66
uint8_t pw1_initial[64]
Definition kdf.h:64
kdf_hash_t hash
Definition kdf.h:53
uint8_t pw3_salt[8]
Definition kdf.h:61
bool has_pw3_salt
Definition kdf.h:60
bool has_pw1_initial
Definition kdf.h:63
uint32_t iter_count
Definition kdf.h:54
bool has_pw1_salt
Definition kdf.h:56