keycard/
messages.rs

1// SPDX-FileCopyrightText: 2025 Foundation Devices, Inc. <hello@foundation.xyz>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use backup_shard::Shard;
5
6use crate::error::{KeycardError, KeycardIdentifyError};
7
8// === External messages ===
9
10/// Shamir secret sharing scheme configuration
11#[derive(Debug, Clone, Copy, PartialEq, Eq, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
12pub struct ShamirScheme {
13    /// Number of shards required to reconstruct the secret
14    pub threshold: usize,
15    /// Total number of shards to generate
16    pub share_count: usize,
17}
18
19impl ShamirScheme {
20    pub const DEFAULT: Self = Self { threshold: 2, share_count: 3 };
21}
22
23impl Default for ShamirScheme {
24    fn default() -> Self { Self::DEFAULT }
25}
26
27#[derive(Debug, Clone, Hash, Eq, PartialEq, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
28pub struct KeycardId(pub Vec<u8>);
29
30impl std::fmt::Display for KeycardId {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:02x?}", self.0) }
32}
33
34#[derive(Debug, server::Message)]
35#[response(Result<(), KeycardError>)]
36pub struct ResetShards;
37
38/// Set the active Shamir scheme for subsequent GenerateShards calls.
39/// Must be called before GenerateShards if you want a non-default scheme.
40/// The scheme is cleared on ResetShards.
41#[derive(Debug, Clone, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
42#[response(Result<(), KeycardError>)]
43pub struct SetShamirScheme(pub ShamirScheme);
44
45#[derive(Debug, server::Message)]
46#[response(Result<(), KeycardError>)]
47pub struct GenerateShards {
48    pub with_magic_backup: bool,
49}
50
51impl server::FromScalar<1> for GenerateShards {
52    fn from_scalar(value: [u32; 1]) -> Self {
53        let with_magic_backup = bool::from_scalar(value);
54        Self { with_magic_backup }
55    }
56}
57
58impl server::AsScalar<1> for GenerateShards {
59    fn as_scalar(&self) -> [u32; 1] { self.with_magic_backup.as_scalar() }
60}
61
62#[derive(Debug, Clone, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
63#[response(Result<Shard, KeycardError>)]
64pub struct PopShard;
65
66#[derive(Debug, Clone, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
67#[response(Result<(), KeycardError>)]
68pub struct PushShard {
69    pub shard: Shard,
70    pub accept_different_device_id: bool,
71}
72
73#[derive(Debug, Clone, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
74#[response(Result<(KeycardId, Option<KeycardIdentifyError>), KeycardError>)]
75pub struct IdentifyKeycard;
76
77#[derive(Debug, Clone, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
78#[response(Result<KeycardId, KeycardError>)]
79pub struct DetectKeycard {
80    pub timeout: std::time::Duration,
81}
82
83#[derive(Debug, Clone, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
84#[response(Result<(), KeycardError>)]
85pub struct StoreShardToKeycard(pub KeycardId);
86
87#[derive(Debug, Clone, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
88#[response(Result<(), KeycardError>)]
89pub struct FormatKeycard(pub KeycardId);
90
91#[derive(Debug, Clone, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
92#[response(Result<LoadedShard, KeycardError>)]
93pub struct LoadShardFromKeycard;
94
95#[derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
96pub struct LoadedShard {
97    pub id: KeycardId,
98    pub has_magic_backup: bool,
99    pub seed_fingerprint: [u8; 32],
100    /// Scheme info (from V1 shards, or default 2-of-3 for V0)
101    pub scheme: ShamirScheme,
102    /// Timestamp when the backup was created (from V1 shards, or 0 for V0)
103    pub timestamp: u32,
104}
105
106#[derive(Debug, server::Message)]
107#[response(Result<(), KeycardError>)]
108pub struct CheckBackup;
109
110#[derive(Debug, Clone, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
111#[response(Result<MasterSeedRestored, KeycardError>)]
112pub struct RestoreMasterSeed;
113
114#[derive(Debug, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
115pub struct MasterSeedRestored {
116    pub seed: security::Seed,
117    pub different_device_id: bool,
118}