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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
//! Types associated with Lair client actor.

use crate::*;
use derive_more::*;
use internal::crypto_box;
use internal::sign_ed25519;
use internal::x25519;

ghost_actor::ghost_chan! {
    /// "Event" types emitted by Lair Client Actor Api.
    pub chan LairClientEvent<LairError> {
        /// The keystore is currently locked - the user
        /// must supply a passphrase in order to unlock.
        fn request_unlock_passphrase() -> String;
    }
}

/// Lair Client Event Sender Type.
pub type LairClientEventSenderType =
    futures::channel::mpsc::Sender<LairClientEvent>;

/// Lair Client Event Receiver Type.
pub type LairClientEventReceiver =
    futures::channel::mpsc::Receiver<LairClientEvent>;

/// Tls keypair algorithm to use.
#[non_exhaustive]
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TlsCertAlg {
    /// Ed25519 Curve.
    PkcsEd25519 = 0x00000200,
    /// Ecdsa Curve 256.
    PkcsEcdsaP256Sha256 = 0x00000201,
    /// Ecdsa Curve 384.
    PkcsEcdsaP384Sha384 = 0x00000202,
}

impl Default for TlsCertAlg {
    fn default() -> Self {
        Self::PkcsEd25519
    }
}

impl TlsCertAlg {
    /// parse a u32 into a LairEntryType enum variant.
    pub fn parse(d: u32) -> LairResult<Self> {
        use TlsCertAlg::*;
        Ok(match d {
            x if x == PkcsEd25519 as u32 => PkcsEd25519,
            x if x == PkcsEcdsaP256Sha256 as u32 => PkcsEcdsaP256Sha256,
            x if x == PkcsEcdsaP384Sha384 as u32 => PkcsEcdsaP384Sha384,
            _ => return Err("invalid tls cert alg".into()),
        })
    }
}

/// Configuration for Tls Certificate Generation.
#[non_exhaustive]
pub struct TlsCertOptions {
    /// Tls keypair algorithm to use.
    pub alg: TlsCertAlg,
}

impl Default for TlsCertOptions {
    fn default() -> Self {
        Self {
            alg: TlsCertAlg::PkcsEd25519,
        }
    }
}

/// Keystore index type.
#[derive(
    Clone,
    Copy,
    Debug,
    Display,
    PartialEq,
    Eq,
    PartialOrd,
    Ord,
    Hash,
    Deref,
    From,
    Into,
)]
pub struct KeystoreIndex(pub u32);

/// Der encoded Tls Certificate bytes.
#[derive(
    Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deref, From, Into,
)]
#[allow(clippy::rc_buffer)]
pub struct Cert(pub Arc<Vec<u8>>);

impl From<Vec<u8>> for Cert {
    fn from(d: Vec<u8>) -> Self {
        Self(Arc::new(d))
    }
}

/// Der encoded pkcs #8 Tls Certificate private key bytes.
#[derive(
    Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deref, From, Into,
)]
#[allow(clippy::rc_buffer)]
pub struct CertPrivKey(pub Arc<Vec<u8>>);

impl From<Vec<u8>> for CertPrivKey {
    fn from(d: Vec<u8>) -> Self {
        Self(Arc::new(d))
    }
}

/// Sni encoded in given Tls Certificate.
#[derive(
    Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deref, From, Into,
)]
#[allow(clippy::rc_buffer)]
pub struct CertSni(pub Arc<String>);

impl From<String> for CertSni {
    fn from(s: String) -> Self {
        Self(Arc::new(s))
    }
}

/// The 32 byte blake2b digest of given Tls Certificate.
#[derive(
    Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deref, From, Into,
)]
#[allow(clippy::rc_buffer)]
pub struct CertDigest(pub Arc<Vec<u8>>);

impl From<Vec<u8>> for CertDigest {
    fn from(d: Vec<u8>) -> Self {
        Self(Arc::new(d))
    }
}

/// The entry type for a given entry.
#[non_exhaustive]
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LairEntryType {
    /// This entry index was deleted or corrupted.
    Invalid = 0x00000000,

    /// Tls Certificate & private key.
    TlsCert = 0x00000100,

    /// Ed25519 algorithm signature keypair.
    SignEd25519 = 0x00000200,

    /// X25519 ECDH keypair.
    X25519 = 0x00000300,
}

impl Default for LairEntryType {
    fn default() -> Self {
        Self::Invalid
    }
}

impl LairEntryType {
    /// parse a u32 into a LairEntryType enum variant.
    pub fn parse(d: u32) -> LairResult<Self> {
        use LairEntryType::*;
        Ok(match d {
            x if x == Invalid as u32 => Invalid,
            x if x == TlsCert as u32 => TlsCert,
            x if x == SignEd25519 as u32 => SignEd25519,
            x if x == X25519 as u32 => X25519,
            _ => return Err("invalide lair entry type".into()),
        })
    }
}

/// Get information about the server we are connected to.
#[non_exhaustive]
#[derive(Debug, Default, Clone, PartialEq)]
pub struct LairServerInfo {
    /// Server name / identifier.
    pub name: String,

    /// Server version.
    pub version: String,
}

ghost_actor::ghost_chan! {
    /// Lair Client Actor Api.
    pub chan LairClientApi<LairError> {
        /// Get lair server info.
        fn lair_get_server_info() -> LairServerInfo;

        /// Get the highest entry index.
        /// Note, some entries my be stubs / erased values.
        fn lair_get_last_entry_index() -> KeystoreIndex;

        /// Get the entry type for a given index.
        fn lair_get_entry_type(
            keystore_index: KeystoreIndex,
        ) -> LairEntryType;

        /// Create a new self-signed tls certificate.
        fn tls_cert_new_self_signed_from_entropy(
            options: TlsCertOptions,
        ) -> (KeystoreIndex, CertSni, CertDigest);

        /// Get tls cert info by keystore index.
        fn tls_cert_get(
            keystore_index: KeystoreIndex,
        ) -> (CertSni, CertDigest);

        /// Fetch the certificate by entry index.
        fn tls_cert_get_cert_by_index(
            keystore_index: KeystoreIndex,
        ) -> Cert;

        /// Fetch the certificate by digest.
        fn tls_cert_get_cert_by_digest(
            cert_digest: CertDigest,
        ) -> Cert;

        /// Fetch the certificate by sni.
        fn tls_cert_get_cert_by_sni(
            cert_sni: CertSni,
        ) -> Cert;

        /// Fetch the certificate private key by entry index.
        fn tls_cert_get_priv_key_by_index(
            keystore_index: KeystoreIndex,
        ) -> CertPrivKey;

        /// Fetch the certificate private key by digest.
        fn tls_cert_get_priv_key_by_digest(
            cert_digest: CertDigest,
        ) -> CertPrivKey;

        /// Fetch the certificate private key by sni.
        fn tls_cert_get_priv_key_by_sni(
            cert_sni: CertSni,
        ) -> CertPrivKey;

        /// Create a new signature ed25519 keypair from entropy.
        fn sign_ed25519_new_from_entropy(
        ) -> (KeystoreIndex, sign_ed25519::SignEd25519PubKey);

        /// Get ed25519 keypair info by keystore index.
        fn sign_ed25519_get(
            keystore_index: KeystoreIndex,
        ) -> sign_ed25519::SignEd25519PubKey;

        /// Generate a signature for message by keystore index.
        fn sign_ed25519_sign_by_index(
            keystore_index: KeystoreIndex,
            message: Arc<Vec<u8>>,
        ) -> sign_ed25519::SignEd25519Signature;

        /// Generate a signature for message by signature pub key.
        fn sign_ed25519_sign_by_pub_key(
            pub_key: sign_ed25519::SignEd25519PubKey,
            message: Arc<Vec<u8>>,
        ) -> sign_ed25519::SignEd25519Signature;

        /// Generate new x25519 keypair from entropy.
        fn x25519_new_from_entropy() -> (KeystoreIndex, x25519::X25519PubKey);

        /// Get x25519 keypair by keystore index.
        fn x25519_get(
            keystore_index: KeystoreIndex,
        ) -> x25519::X25519PubKey;

        /// Generate encrypted crypto box data by sender keystore index for recipient pubkey.
        fn crypto_box_by_index(
            keystore_index: KeystoreIndex,
            recipient: x25519::X25519PubKey,
            data: Arc<crypto_box::CryptoBoxData>,
        ) -> crypto_box::CryptoBoxEncryptedData;

        /// Generate encrypted crypto box data by sender pubkey for recipient pubkey.
        fn crypto_box_by_pub_key(
            pub_key: x25519::X25519PubKey,
            recipient: x25519::X25519PubKey,
            data: Arc<crypto_box::CryptoBoxData>,
        ) -> crypto_box::CryptoBoxEncryptedData;

        /// Open crypto box previously generated by recipient keystore index from sender pubkey.
        fn crypto_box_open_by_index(
            keystore_index: KeystoreIndex,
            sender: x25519::X25519PubKey,
            encrypted_data: Arc<crypto_box::CryptoBoxEncryptedData>,
        ) -> Option<crypto_box::CryptoBoxData>;

        /// Open crypto box previously generated by recipient pubkey from sender pubkey.
        fn crypto_box_open_by_pub_key(
            pub_key: x25519::X25519PubKey,
            sender: x25519::X25519PubKey,
            encrypted_data: Arc<crypto_box::CryptoBoxEncryptedData>
        ) -> Option<crypto_box::CryptoBoxData>;
    }
}

/// Lair Client Sender Type.
pub type LairClientSender = futures::channel::mpsc::Sender<LairClientApi>;