9#include "cdc_msg/MessageTransfer.h"
34#include "esp_random.h"
41static const char*
TAG =
"GPG";
46 {
"mod_gpg.title",
"GPG"},
47 {
"mod_gpg.generate",
"Generate Keys"},
48 {
"mod_gpg.export",
"Export Public"},
49 {
"mod_gpg.reset",
"Reset"},
50 {
"mod_gpg.settings",
"Settings"},
51 {
"mod_gpg.user_pin",
"User PIN"},
52 {
"mod_gpg.admin_pin",
"Admin PIN"},
53 {
"mod_gpg.pin_locked",
"Locked"},
54 {
"mod_gpg.slot_error",
"Slot map error"},
55 {
"mod_gpg.name",
"Name"},
56 {
"mod_gpg.email",
"Email (optional)"},
57 {
"mod_gpg.curve",
"Curve"},
58 {
"mod_gpg.curve_ed25519",
"Ed25519"},
59 {
"mod_gpg.curve_p256",
"P-256"},
60 {
"mod_gpg.no_key",
"No key configured"},
61 {
"mod_gpg.confirm_reset",
"Reset all GPG keys?"},
62 {
"mod_gpg.export_title",
"GPG Public Key"},
63 {
"mod_gpg.send",
"Send Key"},
64 {
"mod_gpg.received",
"Received Keys"},
65 {
"mod_gpg.recv_none",
"No received keys"},
66 {
"mod_gpg.recv_title",
"Received Keys"},
67 {
"mod_gpg.recv_details",
"Key Details"},
68 {
"mod_gpg.recv_sign",
"Cross-Sign"},
69 {
"mod_gpg.recv_export",
"Export"},
70 {
"mod_gpg.recv_forward",
"Forward"},
71 {
"mod_gpg.recv_qr",
"Show QR"},
72 {
"mod_gpg.recv_confirm_sign",
"Sign this key?"},
73 {
"mod_gpg.recv_confirm_del",
"Delete this key?"},
74 {
"mod_gpg.recv_signed",
"Signed"},
75 {
"mod_gpg.recv_unsigned",
"Unsigned"},
76 {
"mod_gpg.recv_export_title",
"Key Export"},
77 {
"mod_gpg.recv_send_sig",
"Send Signature"},
78 {
"mod_gpg.toast_signed",
"Cross-signed"},
79 {
"mod_gpg.toast_sign_fail",
"Sign failed"},
80 {
"mod_gpg.cert_received",
"Incoming key certification"},
81 {
"mod_gpg.mycerts",
"My Certifications"},
82 {
"mod_gpg.mycerts_none",
"No certifications"},
83 {
"mod_gpg.mycerts_details",
"Certification"},
84 {
"mod_gpg.mycerts_confirm_del",
"Delete this certification?"},
92static constexpr const char*
kGpgKeyMime =
"application/pgp-keys";
101 const char* ,
const char* ) {
104 LOG_W(
TAG,
"Rejecting malformed GPG key payload (%u bytes)",
105 static_cast<unsigned>(len));
109 LOG_W(
TAG,
"GPG received-key store full");
117static constexpr const char*
kGpgCertMime =
"application/pgp-signature";
127 const char* ,
const char* ) {
129 uint8_t target_fp[20] = {0};
131 LOG_W(
TAG,
"Rejecting malformed GPG cert payload (%u bytes)",
132 static_cast<unsigned>(len));
137 if (std::memcmp(target_fp, status.
fingerprint, 20) != 0) {
138 LOG_W(
TAG,
"Rejecting cert: targets a different key");
142 LOG_W(
TAG,
"GPG self-cert store full");
168 {
"STATUS",
"",
"Show keys, fingerprints, counters",
cmd_gpg_status},
169 {
"GENERATE",
"<curve> <user_id>",
"Generate SIG+DEC+AUT keys (curve 1=Ed25519, 2=P-256)",
cmd_gpg_generate},
170 {
"EXPORT",
"",
"Print own OpenPGP public key (armored, with certifications)",
cmd_gpg_export},
171 {
"RESET",
"[token]",
"Two-step destructive reset of all GPG keys",
cmd_gpg_reset},
173 {
"RECV_INFO",
"<index>",
"Show a received peer key's details",
cmd_gpg_recv_info},
175 {
"RECV_IMPORT",
"<hex>",
"Import a peer key wire payload (hex) into the received store",
cmd_gpg_recv_import},
176 {
"RECV_CROSS_SIGN",
"<index>",
"Cross-sign a received peer key with our signature key",
cmd_gpg_recv_cross_sign},
177 {
"RECV_EXPORT",
"<index>",
"Export a received peer key (armored, encryptable; adds our cross-signature if present)",
cmd_gpg_recv_export},
178 {
"MYCERT_LIST",
"",
"List third-party certifications collected on the own key",
cmd_gpg_mycert_list},
180 {
"MYCERT_IMPORT",
"<hex>",
"Import a certification return payload (hex) onto the own key",
cmd_gpg_mycert_import},
181 {
"RSA_SELFTEST",
"[bits]",
"Software RSA self-test (gen/sign/verify/decrypt), default 2048",
cmd_gpg_rsa_selftest},
182 {
nullptr,
nullptr,
nullptr,
nullptr},
196 registry.registerCommand({
"GPG",
197 "GPG card: STATUS/GENERATE/EXPORT/RESET",
224 char curveBuf[8] = {};
227 const char* p = args;
228 while (p && *p && std::isspace(
static_cast<unsigned char>(*p))) p++;
235 while (p[i] && !std::isspace(
static_cast<unsigned char>(p[i])) && i + 1 <
sizeof(curveBuf)) {
241 while (p && *p && std::isspace(
static_cast<unsigned char>(*p))) p++;
246 strncpy(userId, p,
sizeof(userId) - 1);
282 const uint64_t now =
static_cast<uint64_t
>(esp_timer_get_time());
286 if (args && *args && token_active && strcmp(args,
s_reset_token) == 0) {
295 esp_fill_random(r,
sizeof(r));
299 "WARNING: this wipes ALL GPG keys (SIG/DEC/AUT), the DEC backup, and PINs.\r\n"
300 "Confirm within 30s: GPG RESET %s\r\n",
304static void fp_to_hex(
const uint8_t* fp,
size_t len,
char* out,
size_t out_size) {
305 if (out_size < len * 2 + 1) {
306 if (out_size > 0) out[0] =
'\0';
309 for (
size_t i = 0; i < len; ++i) {
310 snprintf(out + i * 2, 3,
"%02X", fp[i]);
325 for (uint8_t i = 0; i < n; ++i) {
327 if (!store.getKey(i, &key))
continue;
333 key.
sig_len > 0 ?
"Yes" :
"No");
338 if (!args || !*args)
return false;
340 long v = strtol(args, &end, 10);
341 if (end == args || v < 0 || v > 255)
return false;
342 *out =
static_cast<uint8_t
>(v);
366 strftime(ts_buf,
sizeof(ts_buf),
"%Y-%m-%d %H:%M:%S UTC", &tm_v);
379 char sig_hex[2 * 64 + 1];
393 :
"ERROR: delete failed\r\n");
407 uint32_t now =
static_cast<uint32_t
>(time(
nullptr));
408 uint8_t sig[64] = {0};
459 for (uint8_t i = 0; i < n; ++i) {
461 if (!store.getCert(i, &cert))
continue;
477 :
"ERROR: delete failed\r\n");
481static bool parse_hex(
const char* args, uint8_t* out,
size_t out_cap,
size_t* out_len) {
482 if (!args || !out || !out_len)
return false;
485 for (
const char* p = args; *p; ++p) {
487 if (std::isspace(
static_cast<unsigned char>(c)))
continue;
489 if (c >=
'0' && c <=
'9') v = c -
'0';
490 else if (c >=
'a' && c <=
'f') v = c -
'a' + 10;
491 else if (c >=
'A' && c <=
'F') v = c -
'A' + 10;
496 if (n >= out_cap)
return false;
497 out[n++] =
static_cast<uint8_t
>((hi << 4) | v);
501 if (hi >= 0)
return false;
509 if (!
parse_hex(args, payload,
sizeof(payload), &len)) {
520 :
"ERROR: store full\r\n");
526 if (!
parse_hex(args, payload,
sizeof(payload), &len)) {
531 uint8_t target_fp[20] = {0};
541 if (std::memcmp(target_fp, status.
fingerprint, 20) != 0) {
547 :
"ERROR: store full\r\n");
556 uint16_t bits = 2048;
557 while (args && *args && std::isspace(
static_cast<unsigned char>(*args))) args++;
560 if (v == 2048 || v == 3072 || v == 4096) {
561 bits =
static_cast<uint16_t
>(v);
582 {
nullptr, 0,
false,
nullptr },
583 {
nullptr, 0,
false,
nullptr },
619 switch (
static_cast<GpgMenuAction>(
reinterpret_cast<uintptr_t
>(userData))) {
633 return { label, 0,
false,
reinterpret_cast<void*
>(
static_cast<uintptr_t
>(action)) };
770 bool blocked, uint8_t retries) {
772 snprintf(out, outLen,
"%s [%s]", base,
ui::tr(
"mod_gpg.pin_locked"));
774 snprintf(out, outLen,
"%s (%u)", base,
static_cast<unsigned>(retries));
806 snprintf(fp_hex + i * 2, 3,
"%02X", status.
fingerprint[i]);
809 :
ui::tr(
"mod_gpg.curve_p256");
810 static char detail[512];
811 snprintf(detail,
sizeof(detail),
812 "User-ID: %s\nCurve: %s\nFP: %s\nCreated: %lu\nSign Count: %lu",
813 status.
user_id, curveName, fp_hex,
814 static_cast<unsigned long>(status.
created_at),
815 static_cast<unsigned long>(status.
sign_count));
852 {
nullptr, 0,
false,
nullptr },
853 {
nullptr, 0,
false,
nullptr },
855 curveItems[0].
label =
ui::tr(
"mod_gpg.curve_ed25519");
856 curveItems[1].
label =
ui::tr(
"mod_gpg.curve_p256");
872 if (email_len == 0) {
875 size_t max_len =
sizeof(
user_id) - 1;
876 size_t name_fit = name_len > max_len ? max_len : name_len;
877 size_t email_fit = 0;
878 if (name_fit < max_len) {
879 size_t remaining = max_len - name_fit;
881 email_fit = remaining - 3;
884 if (email_fit == 0) {
912 EXT_RAM_BSS_ATTR
static char armored[4096];
914 static char detail_buf[160];
925 detail_buf[0] =
'\0';
934 snprintf(detail_buf,
sizeof(detail_buf),
"%s\n%s", curveName, alchemy);
938 title_buf[0] ? title_buf :
nullptr,
939 detail_buf[0] ? detail_buf :
nullptr);
992 cdc::msg::MessageTransfer::instance().beginInteractiveSend(
1013 for (uint8_t i = 0; i < n; ++i) {
1015 if (!store.getKey(i, &k)) {
1018 const char* tag = (k.
sig_len > 0) ?
"[x]" :
"[ ]";
1023 reinterpret_cast<void*
>(
static_cast<uintptr_t
>(i)) };
1041 char fp_grouped[64] = {};
1044 for (
size_t i = 0; i < 40 && pos <
sizeof(fp_grouped) - 6; i += 4) {
1045 std::memcpy(fp_grouped + pos, fp_v4 + i, 4);
1047 if (i + 4 < 40) fp_grouped[pos++] =
' ';
1049 fp_grouped[pos] =
'\0';
1053 ?
ui::tr(
"mod_gpg.curve_ed25519")
1054 :
ui::tr(
"mod_gpg.curve_p256");
1059 gmtime_r(&t, &tm_v);
1060 strftime(timeBuf,
sizeof(timeBuf),
"%Y-%m-%d %H:%M", &tm_v);
1063 "%s\n%s\nFP: %s\nRcvd: %s\n%s",
1069 ?
ui::tr(
"mod_gpg.recv_signed")
1070 :
ui::tr(
"mod_gpg.recv_unsigned"));
1089 const uintptr_t action =
reinterpret_cast<uintptr_t
>(userData);
1119 cdc::msg::MessageTransfer::instance().beginInteractiveSend(
1120 kGpgKeyMime, payload,
static_cast<uint32_t
>(len));
1143 cdc::msg::MessageTransfer::instance().beginInteractiveSend(
1152 uint32_t now =
static_cast<uint32_t
>(time(
nullptr));
1153 uint8_t sig[64] = {0};
1201 for (uint8_t i = 0; i < n; ++i) {
1203 if (!store.getCert(i, &c)) {
1209 reinterpret_cast<void*
>(
static_cast<uintptr_t
>(i)) };
1236 gmtime_r(&t, &tm_v);
1237 strftime(timeBuf,
sizeof(timeBuf),
"%Y-%m-%d %H:%M", &tm_v);
1240 "%s\nFP: %s\nRcvd: %s",
1267 static GpgModule inst;
1276 LOG_I(
TAG,
"Initializing GPG module");
1281 if (!slotRange_.hasEcc) {
1287 if (slotRange_.hasRmem) {
1302 cdc::msg::MessageTransfer::instance().registerHandler(
1304 cdc::msg::MessageTransfer::instance().registerHandler(
1323 spec.
name =
"OpenPGP SmartCard";
1335 LOG_W(
TAG,
"Failed to register CCID interface");
1346 cdc::msg::MessageTransfer::instance().unregisterHandler(
kGpgKeyMime);
1347 cdc::msg::MessageTransfer::instance().unregisterHandler(
kGpgCertMime);
1379 if (!items || maxItems == 0)
return 0;
1402 auto&
module = cdc::mod_gpg::GpgModule::instance();
(De)serialisation of a badge-to-badge certification return message.
Transport-agnostic (de)serialisation of a GPG public key.
void mod_gpg_register()
Registers GPG module initializer in global registry.
void gpg_storage_set_rsa_slot_range(uint16_t start, uint16_t end)
Sets the dedicated R-Memory range used for RSA private-key blobs.
void gpg_storage_set_rmem_range(uint16_t rmemStart, uint16_t rmemEnd)
bool gpg_storage_ready(void)
void gpg_storage_set_slot_range(uint16_t eccStart, uint16_t eccEnd)
Internationalization with English fallbacks in code and overlay translations loaded at runtime from a...
#define KEY_FINGERPRINT_MAX_LEN
Shared RAII wrappers for firmware resources.
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_W(tag, fmt,...)
#define LOG_I(tag, fmt,...)
void reportModuleError(const char *name, const char *message)
Records and publishes an operational module error by module name.
bool registerModule(IModule *module)
Registers a module instance in the runtime registry.
static ModuleRegistry & instance()
Returns the singleton module registry instance.
void registerInitializer(ModuleInitFunc initFunc)
Registers a deferred module initializer callback.
void clearModuleErrorByName(const char *name)
Clears stored module error by module name.
static constexpr uint8_t PIN_MAX
static constexpr uint8_t PW3_MIN
static constexpr uint8_t PW1_MIN
static TropicSlotMap & instance()
Returns singleton Tropic slot-map instance.
static UsbManager & instance()
Returns singleton USB manager instance.
void unregisterInterface(UsbHidInterface type, const char *moduleName)
Unregisters a previously registered HID interface.
uint8_t getMenuItems(core::ModuleMenuItem *items, uint8_t maxItems) override
Provides main-menu entry for GPG module.
const char * getName() const override
bool init() override
Initializes GPG module resources and slot assignments.
bool start() override
Starts GPG module and registers USB CCID interface.
static GpgModule & instance()
Returns singleton GPG module instance.
core::IModule::SlotRequest getSlotRequest() const override
Declares slot requirements for GPG module.
void stop() override
Stops GPG module and unregisters CCID interface.
void setSlotRange(const core::IModule::SlotRange &range) override
Stores slot range assigned by module registry.
bool deleteKey(uint8_t index)
Remove one key by sorted index. No-op if index is out of range.
bool getKey(uint8_t index, gpg_recv_key_t *out)
Load one key by sorted index (0..count()-1).
static GpgRecvStore & instance()
static constexpr uint8_t kMaxKeys
Hard ceiling. Past this addKey rejects further inserts.
static GpgSelfCertStore & instance()
bool deleteCert(uint8_t index)
Remove one certification by sorted index. No-op if out of range.
static constexpr uint8_t kMaxCerts
Hard ceiling. Past this addCert rejects further inserts.
static void print(const char *str)
Prints raw string to console.
static void printf(const char *format,...) __attribute__((format(printf
Prints formatted text to console.
static I18n & instance()
Singleton accessor.
void registerEnglishTable(const I18nEntry *entries, std::size_t count)
Append English entries to the lookup table.
static ViewStack & instance()
Returns singleton view-stack instance.
void popToAnchor(IView *anchor)
Pops views until the specified anchor view is the current view.
void push(IView *view, void *context=nullptr)
#define CDC_CURVE_ED25519
uint8_t user_id[FIDO2_USER_ID_MAX_LEN]
bool gpg_set_pending_user_id(const char *user_id)
Stages a user-id string for the next on-device key generation. The string is forwarded to OpenpgpNvsS...
bool gpg_generate_key(uint8_t curve)
Generates SIG / DEC / AUT keys on the device and announces them to the OpenPGP card application (fing...
bool gpg_alchemy_fingerprint(char *buf, size_t len)
Writes the alchemical-word fingerprint of the SIG public key.
bool gpg_get_status(gpg_status_t *status)
Fills status from the OpenPGP card-application state.
#define GPG_FINGERPRINT_LEN
bool gpg_reset(void)
Factory-resets all GPG key material and metadata.
PsramUniquePtr< T > psramAlloc(std::size_t count) noexcept
Allocate count elements of T in PSRAM (8-bit capable region).
static ui::ListItem s_myCertListItems[GpgSelfCertStore::kMaxCerts+1]
static void onReceivedDeleteConfirm(void *)
static void cmd_gpg_rsa_selftest(const char *args)
Serial self-test: runs the software RSA round-trip on the live firmware (no SE / NVS),...
static bool deliverGpgCert(const uint8_t *data, uint32_t len, const char *, const char *)
cdc_msg delivery callback: store a third-party certification on our own key, sent back by a peer that...
static char s_recvListLabels[GpgRecvStore::kMaxKeys][72]
constexpr size_t kGpgCertPayloadMax
Maximum payload size (maximum issuer uid + maximum signature packet).
static char s_myCertDetailText[320]
static ui::ListItem s_settingsItems[]
static ui::ListView s_recvActionView
static ui::ListItem makeMenuItem(const char *label, GpgMenuAction action)
static void cmd_gpg_recv_info(const char *args)
static uint8_t gpg_retries_pw3()
Returns remaining retries for OpenPGP PW3.
static bool gpg_change_pw1(const char *, const char *newPin)
Changes OpenPGP PW1 value.
static ui::QRCodeView s_qrView
static void showSettings()
Shows GPG settings menu.
static bool parse_hex(const char *args, uint8_t *out, size_t out_cap, size_t *out_len)
Decode an ASCII-hex string into out. Skips ASCII whitespace between bytes.
static constexpr uint64_t RESET_TOKEN_TIMEOUT_US
static uint64_t s_reset_token_ts_us
static void cmd_gpg_recv_cross_sign(const char *args)
static void showSendKey()
static ui::ListItem s_menuItems[8]
static void cmd_gpg_status(const char *args)
Serial command printing current GPG key status.
static void showReceivedDetail()
static bool s_viewsInitialized
static void showMyCertifications()
static void registerStrings()
static char s_userPinLabel[48]
static ui::ListView s_myCertListView
My-certifications (third-party signatures on our own key) UI state.
static void cmd_gpg_mycert_delete(const char *args)
static bool gpg_verify_pw1(const char *pin)
Verifies OpenPGP PW1 using persistent pin-storage backend.
static void onReceivedSignConfirm(void *)
static ui::ListView s_settingsView
bool gpgBuildOwnSignedKeyArmored(char *out, size_t out_size, size_t *out_len)
Build an ASCII-armored OpenPGP block for the badge's own public key, appending every stored third-par...
static constexpr const char * kGpgKeyMime
MIME type for badge-to-badge public-key transfer over cdc_msg.
static ui::ListView s_menuView
static gpg_self_cert_t s_myCertSelected
static void onWizardEmail(const char *text)
Saves wizard email and opens curve selection.
static void rebuildMyCertList()
bool gpgParseCertPayload(const uint8_t *data, size_t len, gpg_self_cert_t *out, uint8_t out_target_fp[20])
Parse a certification return message into a self-cert record.
static gpg_recv_key_t s_recvSelectedKey
size_t gpgBuildRecvKeyPayload(const gpg_recv_key_t &key, uint8_t *out, size_t out_size)
Serialise a stored received key into the wire payload (for forwarding).
size_t gpgBuildOwnKeyPayload(uint8_t *out, size_t out_size)
Serialise the badge's own public key into the wire payload.
bool gpgParseKeyPayload(const uint8_t *data, size_t len, gpg_recv_key_t *out)
Parse a wire payload into a key record, computing the V5 fingerprint.
static bool gpg_change_pw3(const char *, const char *newPin)
Changes OpenPGP PW3 value.
constexpr ui::I18nEntry kStrings[]
static void onMenuSelect(uint16_t, void *userData)
Handles GPG main-menu selections via the entry's userData tag.
static bool gpg_blocked_pw1()
Returns whether OpenPGP PW1 is blocked.
static void rebuildMenu()
Rebuilds GPG main menu labels and populates userData tags.
static void showExport()
Exports public key to serial output and QR view.
static void onResetConfirm(void *)
Confirm callback resetting all GPG key material.
static WizardState s_wizard
static void cmd_gpg_recv_list(const char *args)
static void onWizardCurve(uint16_t index, void *)
Finalizes wizard curve selection and triggers key generation.
static ui::ListView s_recvListView
Received-keys list UI state.
constexpr uint8_t kGpgRecvFlagVerified
constexpr size_t kGpgKeyPayloadMax
Maximum payload size (P-256 + maximum user id + DEC block).
static void cmd_gpg(const char *args)
static void showStatus()
Displays current GPG key status and metadata.
static ui::ListItem s_recvActionItems[6]
static char s_reset_token[7]
Serial command resetting GPG key material.
static void rebuildReceivedList()
static void registerCommands()
Registers serial commands exposed by GPG module.
static void cmd_gpg_recv_delete(const char *args)
static void cmd_gpg_recv_import(const char *args)
static void onReceivedListSelect(uint16_t index, void *)
static constexpr const char * CMD_MODULE
static void onMyCertDeleteConfirm(void *)
static ui::PinChangeView s_pinChangeView
static ui::ListView s_curveView
static char s_adminPinLabel[48]
static uint8_t gpg_retries_pw1()
Returns remaining retries for OpenPGP PW1.
static uint8_t s_myCertSelectedIndex
static void showReceivedKeys()
static bool deliverGpgKey(const uint8_t *data, uint32_t len, const char *, const char *)
cdc_msg delivery callback: store a public key pushed by a peer.
bool gpgCrossSign(const gpg_recv_key_t &target, uint32_t sig_creation_time, uint8_t out_sig[64])
Cross-sign a received key with the badge's own SIG ECC slot.
static const cdc::serial::SubCommand kGpgSubs[]
bool gpgBuildPublicKeyArmored(const gpg_recv_key_t &key, char *out, size_t out_size, size_t *out_len)
Build an ASCII-armored OpenPGP public-key block (no signature).
static char s_myCertLabels[GpgSelfCertStore::kMaxCerts][72]
static void onReceivedActionSelect(uint16_t index, void *)
static constexpr const char * kGpgCertMime
MIME type for badge-to-badge certification return messages over cdc_msg.
static void cmd_gpg_recv_export(const char *args)
static void cmd_gpg_export(const char *args)
Serial command exporting GPG public key in PEM format.
static void wizardStart()
Starts key-generation wizard flow.
static void cmd_gpg_reset(const char *args)
static void onGpgPinComplete(bool)
Pin-change completion callback returning to previous view.
static uint8_t s_recvSelectedIndex
static bool s_commandsRegistered
static bool gpg_blocked_pw3()
Returns whether OpenPGP PW3 is blocked.
static ui::ListItem s_recvListItems[GpgRecvStore::kMaxKeys+1]
static void onMyCertListSelect(uint16_t index, void *)
static char s_recvExportBuf[4096]
static void cmd_gpg_mycert_list(const char *args)
static bool parse_index(const char *args, uint8_t *out)
static void confirmReset()
Opens reset confirmation dialog.
static ui::T9InputView s_t9Input
size_t gpgBuildCertPayload(const gpg_recv_key_t &signed_key, uint8_t *out, size_t out_size)
Serialise a certification return message for a cross-signed key.
static void onSettingsSelect(uint16_t index, void *)
Handles settings-menu selection for PW1/PW3 change flow.
static char s_recvDetailText[640]
static void cmd_gpg_mycert_import(const char *args)
static bool gpg_verify_pw3(const char *pin)
Verifies OpenPGP PW3 using persistent pin-storage backend.
static void onWizardName(const char *text)
Saves wizard name and opens email step.
static void formatPinLabel(char *out, size_t outLen, const char *base, bool blocked, uint8_t retries)
Formats a PIN settings label with its remaining-retry status.
static void fp_to_hex(const uint8_t *fp, size_t len, char *out, size_t out_size)
static void cmd_gpg_generate(const char *args)
Serial command generating GPG key with selected curve and user-id.
static ui::InfoView s_infoView
bool gpgBuildReceivedKeyArmored(const gpg_recv_key_t &key, char *out, size_t out_size, size_t *out_len)
Build an ASCII-armored OpenPGP block for a received peer key.
ICommandRegistry & getCommandRegistry()
Returns singleton command-registry interface.
void dispatchSubCommand(const char *parent, const char *args, const SubCommand *table)
Routes a sub-command line to its handler.
const char * tr(const char *key)
Look up a translation by string key.
void showToast(const char *message, uint16_t durationMs=1500)
Shows a plain toast message.
InfoView * showInfo(const char *title, const char *text, const char *hint=nullptr)
Shows a shared info view instance and pushes it onto the view stack.
void showConfirm(const char *message, ConfirmView::ConfirmCallback onConfirm, ConfirmView::CancelCallback onCancel=nullptr, ConfirmView::Icon icon=ConfirmView::Icon::QUESTION, void *userData=nullptr)
Shows a shared modal confirmation dialog instance.
void showToastSuccess(const char *message, uint16_t durationMs=1500)
Shows a success toast message.
void showToastInfo(const char *message, uint16_t durationMs=1500)
Shows an informational toast message.
void showToastError(const char *message, uint16_t durationMs=1500)
Shows an error toast message.
bool openpgp_has_any_key(void)
Reports whether any of the SIG / DEC / AUT roles has a non-zero fingerprint configured....
uint8_t pin_storage_openpgp_pw1_retries(void)
bool pin_storage_openpgp_pw1_blocked(void)
bool pin_storage_openpgp_change_pw3(const char *new_pin)
uint8_t pin_storage_openpgp_pw3_retries(void)
bool pin_storage_openpgp_verify_pw1(const char *pin)
bool pin_storage_openpgp_verify_pw3(const char *pin)
bool pin_storage_openpgp_change_pw1(const char *new_pin)
bool pin_storage_openpgp_pw3_blocked(void)
bool gpg_rsa_selftest(uint16_t n_bits)
End-to-end self-test: generate a key, serialise/reload its blob, then sign+verify and encrypt+decrypt...
One GPG public key received from another badge.
uint8_t fingerprint_v4[20]
uint8_t fingerprint_v5[32]
One third-party certification received over the badge's own key.
char issuer_uid[64]
Issuer user-id (display only).
uint8_t issuer_fp_v4[20]
Issuer (signer) v4 fingerprint.
Snapshot of the current OpenPGP card-application state for UI display.
Single English translation entry.