CDC Badge OS
Firmware for the CDC Badge v1.0 hardware security key
Loading...
Searching...
No Matches
KeyFingerprint.cpp
Go to the documentation of this file.
1
4
7#include "mbedtls/sha256.h"
8#include <string.h>
9
11static constexpr size_t SHA256_DIGEST_SIZE = 32;
13static constexpr size_t P256_PUBKEY_RAW_SIZE = 64;
15static constexpr size_t ED25519_PUBKEY_SIZE = 32;
16
20static const char* const ALCHEMY_WORDS[32] = {
21 "Fire", "Water", "Earth", "Air",
22 "Aether", "Sulfur", "Mercury", "Salt",
23 "Gold", "Silver", "Copper", "Iron",
24 "Tin", "Lead", "Antimony", "Arsenic",
25 "Bismuth", "Phosphorus", "Platinum", "Zinc",
26 "Magnesium", "Potassium", "Vitriol", "Aquafortis",
27 "Alkahest", "Azoth", "Cinnabar", "Nitre",
28 "Calx", "Regulus", "Quintessence","Stone"
29};
30
36const char* key_fingerprint_word(uint8_t index) {
37 if (index >= 32) return "?";
38 return ALCHEMY_WORDS[index];
39}
40
49bool key_fingerprint_from_pubkey(const uint8_t* pubkey, size_t pubkey_len,
50 char* buf, size_t len) {
51 if (!pubkey || !buf || len < KEY_FINGERPRINT_MAX_LEN || pubkey_len == 0) {
52 return false;
53 }
54
55 uint8_t hash[SHA256_DIGEST_SIZE];
56 mbedtls_sha256(pubkey, pubkey_len, hash, 0);
57
58 uint8_t indices[KEY_FINGERPRINT_WORD_COUNT];
59 indices[0] = (hash[0] >> 3) & 0x1F;
60 indices[1] = ((hash[0] << 2) | (hash[1] >> 6)) & 0x1F;
61 indices[2] = (hash[1] >> 1) & 0x1F;
62 indices[3] = ((hash[1] << 4) | (hash[2] >> 4)) & 0x1F;
63 indices[4] = ((hash[2] << 1) | (hash[3] >> 7)) & 0x1F;
64
65 buf[0] = '\0';
66 for (size_t i = 0; i < KEY_FINGERPRINT_WORD_COUNT; i++) {
67 if (i > 0) {
68 strlcat(buf, " ", len);
69 }
70 strlcat(buf, ALCHEMY_WORDS[indices[i]], len);
71 }
72
73 return true;
74}
75
83bool key_fingerprint_generate(uint8_t slot, char* buf, size_t len) {
84 if (!buf || len < KEY_FINGERPRINT_MAX_LEN) {
85 return false;
86 }
87
89 if (!se) {
90 return false;
91 }
92
93 uint8_t pubkey[P256_PUBKEY_RAW_SIZE] = {};
95 if (se->eccGetPublicKey(slot, pubkey, &curve) != cdc::hal::SeResult::OK) {
96 strlcpy(buf, "(no key)", len);
97 return false;
98 }
99
101 return key_fingerprint_from_pubkey(pubkey, pubkey_len, buf, len);
102}
static constexpr size_t P256_PUBKEY_RAW_SIZE
Uncompressed P-256 public key, raw X||Y coordinates (no SEC1 0x04 prefix).
const char * key_fingerprint_word(uint8_t index)
Returns alchemical word for 5-bit index.
bool key_fingerprint_from_pubkey(const uint8_t *pubkey, size_t pubkey_len, char *buf, size_t len)
Generates human-readable fingerprint from public key bytes.
static const char *const ALCHEMY_WORDS[32]
Lookup table of 32 alchemical element labels (5-bit index space).
bool key_fingerprint_generate(uint8_t slot, char *buf, size_t len)
Reads public key from secure element slot and generates fingerprint.
#define KEY_FINGERPRINT_MAX_LEN
#define KEY_FINGERPRINT_WORD_COUNT
#define ED25519_PUBKEY_SIZE
Ed25519 raw public key size in bytes.
Definition constants.h:56
#define SHA256_DIGEST_SIZE
SHA-256 digest output size in bytes (FIPS 180-4).
Definition constants.h:37
uint8_t curve
ISecureElement * getSecureElementInstance()
Returns singleton secure-element stub instance.