• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

oasisprotocol / oasis-core / #4833

22 Apr 2024 10:02AM UTC coverage: 45.073% (-1.9%) from 46.95%
#4833

Pull #5642

kostko
Update Rust dependencies
Pull Request #5642: Add support for mock SGX builds

14 of 43 new or added lines in 7 files covered. (32.56%)

218 existing lines in 7 files now uncovered.

3787 of 8402 relevant lines covered (45.07%)

0.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/keymanager/src/runtime/secrets.rs
1
//! Methods exported to remote clients via EnclaveRPC.
2
use std::{
3
    collections::{HashMap, HashSet},
4
    convert::TryInto,
5
    sync::Arc,
6
};
7

8
use anyhow::Result;
9

10
use oasis_core_runtime::{
11
    common::{
12
        crypto::{
13
            mrae::{
14
                deoxysii::{self, Opener},
15
                nonce::Nonce,
16
            },
17
            signature::{self, Signer},
18
            x25519,
19
        },
20
        namespace::Namespace,
21
        sgx::EnclaveIdentity,
22
    },
23
    consensus::{
24
        beacon::EpochTime,
25
        keymanager::{
26
            EncryptedEphemeralSecret, EncryptedMasterSecret, EncryptedSecret,
27
            SignedEncryptedEphemeralSecret, SignedEncryptedMasterSecret,
28
        },
29
        state::{
30
            beacon::ImmutableState as BeaconState,
31
            keymanager::{ImmutableState as KeyManagerState, Status},
32
            registry::ImmutableState as RegistryState,
33
        },
34
        verifier::Verifier,
35
    },
36
    enclave_rpc::{
37
        dispatcher::{Handler, Method as RpcMethod, MethodDescriptor as RpcMethodDescriptor},
38
        types::Kind as RpcKind,
39
        Context as RpcContext,
40
    },
41
    future::block_on,
42
    identity::Identity,
43
    policy::PolicyVerifier,
44
    protocol::ProtocolUntrustedLocalStorage,
45
    Protocol, BUILD_INFO,
46
};
47

48
use crate::{
49
    api::{
50
        EphemeralKeyRequest, GenerateEphemeralSecretRequest, GenerateEphemeralSecretResponse,
51
        GenerateMasterSecretRequest, GenerateMasterSecretResponse, InitRequest, InitResponse,
52
        KeyManagerError, LoadEphemeralSecretRequest, LoadMasterSecretRequest, LongTermKeyRequest,
53
        ReplicateEphemeralSecretRequest, ReplicateEphemeralSecretResponse,
54
        ReplicateMasterSecretRequest, ReplicateMasterSecretResponse, SignedInitResponse,
55
        LOCAL_METHOD_GENERATE_EPHEMERAL_SECRET, LOCAL_METHOD_GENERATE_MASTER_SECRET,
56
        LOCAL_METHOD_INIT, LOCAL_METHOD_LOAD_EPHEMERAL_SECRET, LOCAL_METHOD_LOAD_MASTER_SECRET,
57
        METHOD_GET_OR_CREATE_EPHEMERAL_KEYS, METHOD_GET_OR_CREATE_KEYS,
58
        METHOD_GET_PUBLIC_EPHEMERAL_KEY, METHOD_GET_PUBLIC_KEY, METHOD_REPLICATE_EPHEMERAL_SECRET,
59
        METHOD_REPLICATE_MASTER_SECRET,
60
    },
61
    client::RemoteClient,
62
    crypto::{
63
        kdf::{Kdf, State},
64
        pack_runtime_id_epoch, pack_runtime_id_generation_epoch, unpack_encrypted_secret_nonce,
65
        KeyPair, Secret, SignedPublicKey, SECRET_SIZE,
66
    },
67
    policy::Policy,
68
    secrets::{KeyManagerSecretProvider, SecretProvider},
69
};
70

71
/// Maximum age of an ephemeral key in the number of epochs.
72
const MAX_EPHEMERAL_KEY_AGE: EpochTime = 10;
73
/// Maximum age of a fresh height in the number of blocks.
74
///
75
/// A height is considered fresh if it is not more than specified amount
76
/// of blocks lower than the height of the latest trust root.
77
const MAX_FRESH_HEIGHT_AGE: u64 = 50;
78

79
/// Master and ephemeral secrets RPC handler.
80
pub struct Secrets {
81
    /// Key manager runtime ID.
82
    pub runtime_id: Namespace,
83
    /// The current runtime identity if any.
84
    pub identity: Arc<Identity>,
85
    /// Consensus verifier.
86
    pub consensus_verifier: Arc<dyn Verifier>,
87
    /// Untrusted local storage.
88
    pub storage: Arc<ProtocolUntrustedLocalStorage>,
89
    /// Low-level access to the underlying Runtime Host Protocol.
90
    pub protocol: Arc<Protocol>,
91
}
92

93
impl Secrets {
94
    pub fn new(
×
95
        identity: Arc<Identity>,
96
        consensus_verifier: Arc<dyn Verifier>,
97
        protocol: Arc<Protocol>,
98
    ) -> Self {
99
        let storage = Arc::new(ProtocolUntrustedLocalStorage::new(protocol.clone()));
×
100
        let runtime_id = protocol.get_runtime_id();
×
101

102
        Self {
103
            runtime_id,
104
            identity,
105
            consensus_verifier,
106
            storage,
107
            protocol,
108
        }
109
    }
110

111
    /// Initialize the Kdf.
112
    pub fn init_kdf(&self, req: &InitRequest) -> Result<SignedInitResponse> {
×
113
        let status = req.status.clone();
×
114
        let status = self.validate_key_manager_status(status)?;
×
115

116
        // Empty policies are allowed only in unsafe builds.
117
        let policy = Policy::global();
×
118
        let policy_checksum = policy.init(&self.storage, status.policy)?;
×
119

120
        // Initialize or update the KDF.
121
        let generation = status.generation;
×
122
        let checksum = status.checksum;
×
123
        let nodes = status.nodes;
×
124
        let epoch = self.consensus_epoch()?;
×
125
        let client = self.key_manager_client_for_replication();
×
126
        let provider = KeyManagerSecretProvider::new(client, nodes);
×
127

128
        let kdf = Kdf::global();
×
129
        let state = kdf.init(
×
130
            &self.storage,
×
131
            self.runtime_id,
×
132
            generation,
133
            checksum,
×
134
            epoch,
135
            &provider,
136
        )?;
137

138
        // State is up-to-date, build the response and sign it with the RAK.
139
        self.sign_init_response(state, policy_checksum)
×
140
    }
141

142
    /// See `Kdf::get_or_create_keys`.
143
    pub fn get_or_create_keys(
×
144
        &self,
145
        ctx: &RpcContext,
146
        req: &LongTermKeyRequest,
147
    ) -> Result<KeyPair> {
148
        Self::authorize_private_key_generation(ctx, &req.runtime_id)?;
×
149
        self.validate_height_freshness(req.height)?;
×
150

151
        Kdf::global().get_or_create_longterm_keys(
×
152
            &self.storage,
×
153
            req.runtime_id,
×
154
            req.key_pair_id,
×
155
            req.generation,
×
156
        )
157
    }
158

159
    /// See `Kdf::get_public_key`.
160
    pub fn get_public_key(&self, req: &LongTermKeyRequest) -> Result<SignedPublicKey> {
×
161
        // No authentication or authorization.
162
        // Absolutely anyone is allowed to query public long-term keys.
163

164
        let kdf = Kdf::global();
×
165
        let pk = kdf.get_public_longterm_key(
×
166
            &self.storage,
×
167
            req.runtime_id,
×
168
            req.key_pair_id,
×
169
            req.generation,
×
170
        )?;
171
        let sig = kdf.sign_public_key(pk, req.runtime_id, req.key_pair_id, None)?;
×
172
        Ok(sig)
×
173
    }
174

175
    /// See `Kdf::get_or_create_ephemeral_keys`.
176
    pub fn get_or_create_ephemeral_keys(
×
177
        &self,
178
        ctx: &RpcContext,
179
        req: &EphemeralKeyRequest,
180
    ) -> Result<KeyPair> {
181
        Self::authorize_private_key_generation(ctx, &req.runtime_id)?;
×
182
        self.validate_ephemeral_key_epoch(req.epoch)?;
×
183
        self.validate_height_freshness(req.height)?;
×
184

185
        Kdf::global().get_or_create_ephemeral_keys(req.runtime_id, req.key_pair_id, req.epoch)
×
186
    }
187

188
    /// See `Kdf::get_public_ephemeral_key`.
189
    pub fn get_public_ephemeral_key(&self, req: &EphemeralKeyRequest) -> Result<SignedPublicKey> {
×
190
        // No authentication or authorization.
191
        // Absolutely anyone is allowed to query public ephemeral keys.
192
        self.validate_ephemeral_key_epoch(req.epoch)?;
×
193

194
        let kdf = Kdf::global();
×
195
        let pk = kdf.get_public_ephemeral_key(req.runtime_id, req.key_pair_id, req.epoch)?;
×
196
        let sig = kdf.sign_public_key(pk, req.runtime_id, req.key_pair_id, Some(req.epoch))?;
×
197

198
        Ok(sig)
×
199
    }
200

201
    /// See `Kdf::replicate_master_secret`.
202
    pub fn replicate_master_secret(
×
203
        &self,
204
        ctx: &RpcContext,
205
        req: &ReplicateMasterSecretRequest,
206
    ) -> Result<ReplicateMasterSecretResponse> {
207
        Self::authorize_secret_replication(ctx)?;
×
208
        self.validate_height_freshness(req.height)?;
×
209

210
        let master_secret = Kdf::global().replicate_master_secret(&self.storage, req.generation)?;
×
211
        let checksum = Kdf::load_checksum(&self.storage, req.generation);
×
212

213
        Ok(ReplicateMasterSecretResponse {
×
214
            master_secret,
×
215
            checksum,
216
        })
217
    }
218

219
    /// See `Kdf::replicate_ephemeral_secret`.
220
    pub fn replicate_ephemeral_secret(
×
221
        &self,
222
        ctx: &RpcContext,
223
        req: &ReplicateEphemeralSecretRequest,
224
    ) -> Result<ReplicateEphemeralSecretResponse> {
225
        Self::authorize_secret_replication(ctx)?;
×
226
        self.validate_height_freshness(req.height)?;
×
227

228
        let ephemeral_secret = Kdf::global().replicate_ephemeral_secret(req.epoch)?;
×
229
        Ok(ReplicateEphemeralSecretResponse { ephemeral_secret })
×
230
    }
231

232
    /// Generate a master secret and encrypt it using the key manager's REK keys.
233
    pub fn generate_master_secret(
×
234
        &self,
235
        req: &GenerateMasterSecretRequest,
236
    ) -> Result<GenerateMasterSecretResponse> {
237
        let kdf = Kdf::global();
×
238
        let runtime_id = kdf.runtime_id()?;
×
239

240
        // Allow generating a secret for the next epoch only.
241
        let epoch = self.consensus_epoch()? + 1;
×
242
        if epoch != req.epoch {
×
243
            return Err(KeyManagerError::InvalidEpoch(epoch, req.epoch).into());
×
244
        }
245

246
        // Generate a secret and encrypt it.
247
        // Note that the checksum can be computed for the next generation only.
248
        let generation = req.generation;
×
249
        let secret = Secret::generate();
×
250
        let checksum = kdf.checksum_master_secret_proposal(runtime_id, &secret, generation)?;
×
251
        let additional_data = pack_runtime_id_generation_epoch(&runtime_id, generation, epoch);
×
252
        let secret = self.encrypt_secret(secret, checksum, additional_data, runtime_id)?;
×
253

254
        // Sign the secret.
255
        let signer: Arc<dyn Signer> = self.identity.clone();
×
256
        let secret = EncryptedMasterSecret {
257
            runtime_id,
258
            generation,
259
            epoch,
260
            secret,
261
        };
262
        let signed_secret = SignedEncryptedMasterSecret::new(secret, &signer)?;
×
263

264
        Ok(GenerateMasterSecretResponse { signed_secret })
×
265
    }
266

267
    /// Generate an ephemeral secret and encrypt it using the key manager's REK keys.
268
    pub fn generate_ephemeral_secret(
×
269
        &self,
270
        req: &GenerateEphemeralSecretRequest,
271
    ) -> Result<GenerateEphemeralSecretResponse> {
272
        let kdf = Kdf::global();
×
273
        let runtime_id = kdf.runtime_id()?;
×
274

275
        // Allow generating a secret for the next epoch only.
276
        let epoch = self.consensus_epoch()? + 1;
×
277
        if epoch != req.epoch {
×
278
            return Err(KeyManagerError::InvalidEpoch(epoch, req.epoch).into());
×
279
        }
280

281
        // Generate a secret and encrypt it.
282
        let secret = Secret::generate();
×
283
        let checksum = Kdf::checksum_ephemeral_secret(&runtime_id, &secret, epoch);
×
284
        let additional_data = pack_runtime_id_epoch(&runtime_id, epoch);
×
285
        let secret = self.encrypt_secret(secret, checksum, additional_data, runtime_id)?;
×
286

287
        // Sign the secret.
288
        let signer: Arc<dyn Signer> = self.identity.clone();
×
289
        let secret = EncryptedEphemeralSecret {
290
            runtime_id,
291
            epoch,
292
            secret,
293
        };
294
        let signed_secret = SignedEncryptedEphemeralSecret::new(secret, &signer)?;
×
295

296
        Ok(GenerateEphemeralSecretResponse { signed_secret })
×
297
    }
298

299
    /// Encrypt a secret using the Deoxys-II MRAE algorithm and the key manager's REK keys.
300
    fn encrypt_secret(
×
301
        &self,
302
        secret: Secret,
303
        checksum: Vec<u8>,
304
        additional_data: Vec<u8>,
305
        runtime_id: Namespace,
306
    ) -> Result<EncryptedSecret> {
307
        // Fetch REK keys of the key manager committee members.
308
        let rek_keys = self.key_manager_rek_keys(runtime_id)?;
×
309
        let rek_keys: HashSet<_> = rek_keys.values().collect();
×
310
        // Abort if our REK hasn't been published.
311
        if !rek_keys.contains(&self.identity.public_rek()) {
×
312
            return Err(KeyManagerError::REKNotPublished.into());
×
313
        }
314
        // Encrypt the secret.
315
        let priv_key = x25519::PrivateKey::generate();
×
316
        let pub_key = x25519::PublicKey::from(&priv_key);
×
317
        let mut nonce = Nonce::generate();
×
318
        let plaintext = secret.0.to_vec();
×
319
        let mut ciphertexts = HashMap::new();
×
320
        for &rek in rek_keys.iter() {
×
321
            nonce.increment()?;
×
322

323
            let mut ciphertext = deoxysii::box_seal(
324
                &nonce,
×
325
                plaintext.clone(),
×
326
                additional_data.clone(),
×
327
                &rek.0,
328
                &priv_key.0,
329
            )?;
330
            ciphertext.extend_from_slice(&nonce.to_vec());
×
331

332
            ciphertexts.insert(*rek, ciphertext);
×
333
        }
334

335
        Ok(EncryptedSecret {
×
336
            checksum,
×
337
            pub_key,
338
            ciphertexts,
×
339
        })
340
    }
341

342
    /// Decrypt and store a proposal for the next master secret.
343
    pub fn load_master_secret(&self, req: &LoadMasterSecretRequest) -> Result<()> {
×
344
        let signed_secret = self.validate_signed_master_secret(&req.signed_secret)?;
×
345

346
        let secret = match self.decrypt_master_secret(&signed_secret)? {
×
347
            Some(secret) => secret,
×
348
            None => return Ok(()),
×
349
        };
350

351
        Kdf::global().add_master_secret_proposal(
×
352
            &self.storage,
×
353
            &signed_secret.runtime_id,
×
354
            secret,
×
355
            signed_secret.generation,
×
356
            &signed_secret.secret.checksum,
357
        )
358
    }
359

360
    /// Decrypt and store an ephemeral secret. If decryption fails, try to replicate the secret
361
    /// from another key manager enclave.
362
    pub fn load_ephemeral_secret(&self, req: &LoadEphemeralSecretRequest) -> Result<()> {
×
363
        let signed_secret = self.validate_signed_ephemeral_secret(&req.signed_secret)?;
×
364

365
        let secret = match self.decrypt_ephemeral_secret(&signed_secret)? {
×
366
            Some(secret) => secret,
×
367
            None => {
368
                let nodes = self.nodes_with_ephemeral_secret(&signed_secret)?;
×
369
                let client = self.key_manager_client_for_replication();
×
370

371
                KeyManagerSecretProvider::new(client, nodes)
×
372
                    .ephemeral_secret_iter(signed_secret.epoch)
×
373
                    .find(|secret| {
×
374
                        let checksum = Kdf::checksum_ephemeral_secret(
×
375
                            &signed_secret.runtime_id,
×
376
                            secret,
377
                            signed_secret.epoch,
×
378
                        );
379
                        checksum == signed_secret.secret.checksum
×
380
                    })
381
                    .ok_or(KeyManagerError::EphemeralSecretNotReplicated(
×
382
                        signed_secret.epoch,
×
383
                    ))?
384
            }
385
        };
386

387
        Kdf::global().add_ephemeral_secret(
×
388
            &signed_secret.runtime_id,
×
389
            secret,
×
390
            signed_secret.epoch,
×
391
            &signed_secret.secret.checksum,
392
        )
393
    }
394

395
    /// Decrypt master secret with local REK key.
396
    fn decrypt_master_secret(&self, secret: &EncryptedMasterSecret) -> Result<Option<Secret>> {
×
397
        let generation = secret.generation;
×
398
        let epoch = secret.epoch;
×
399
        let runtime_id = secret.runtime_id;
×
400
        let rek = self.identity.public_rek();
×
401

402
        let ciphertext = match secret.secret.ciphertexts.get(&rek) {
×
403
            Some(ciphertext) => ciphertext,
×
404
            None => return Ok(None),
×
405
        };
406

407
        let (ciphertext, nonce) =
×
408
            unpack_encrypted_secret_nonce(ciphertext).ok_or(KeyManagerError::InvalidCiphertext)?;
409
        let additional_data = pack_runtime_id_generation_epoch(&runtime_id, generation, epoch);
×
410
        let plaintext = self.identity.box_open(
×
411
            &nonce,
412
            ciphertext,
×
413
            additional_data,
×
414
            &secret.secret.pub_key.0,
×
415
        )?;
416

417
        if plaintext.len() != SECRET_SIZE {
×
418
            return Err(KeyManagerError::InvalidCiphertext.into());
×
419
        }
420

421
        let secret = Secret(plaintext.try_into().expect("slice with incorrect length"));
×
422

423
        Ok(Some(secret))
×
424
    }
425

426
    /// Decrypt ephemeral secret with local REK key.
427
    fn decrypt_ephemeral_secret(
×
428
        &self,
429
        secret: &EncryptedEphemeralSecret,
430
    ) -> Result<Option<Secret>> {
431
        let epoch = secret.epoch;
×
432
        let runtime_id = secret.runtime_id;
×
433
        let rek = self.identity.public_rek();
×
434

435
        let ciphertext = match secret.secret.ciphertexts.get(&rek) {
×
436
            Some(ciphertext) => ciphertext,
×
437
            None => return Ok(None),
×
438
        };
439

440
        let (ciphertext, nonce) =
×
441
            unpack_encrypted_secret_nonce(ciphertext).ok_or(KeyManagerError::InvalidCiphertext)?;
442
        let additional_data = pack_runtime_id_epoch(&runtime_id, epoch);
×
443
        let plaintext = self.identity.box_open(
×
444
            &nonce,
445
            ciphertext,
×
446
            additional_data,
×
447
            &secret.secret.pub_key.0,
×
448
        )?;
449

450
        if plaintext.len() != SECRET_SIZE {
×
451
            return Err(KeyManagerError::InvalidCiphertext.into());
×
452
        }
453

454
        let secret = Secret(plaintext.try_into().expect("slice with incorrect length"));
×
455

456
        Ok(Some(secret))
×
457
    }
458

459
    /// Key manager client for master and ephemeral secret replication.
460
    fn key_manager_client_for_replication(&self) -> RemoteClient {
×
461
        RemoteClient::new_runtime_with_enclaves_and_policy(
462
            self.runtime_id,
×
463
            Some(self.runtime_id),
×
464
            Policy::global().may_replicate_from(),
×
465
            self.identity.quote_policy(),
×
466
            self.protocol.clone(),
×
467
            self.consensus_verifier.clone(),
×
468
            self.identity.clone(),
×
469
            1, // Not used, doesn't matter.
470
            vec![],
×
471
        )
472
    }
473

474
    /// Create init response and sign it with RAK.
475
    fn sign_init_response(
×
476
        &self,
477
        state: State,
478
        policy_checksum: Vec<u8>,
479
    ) -> Result<SignedInitResponse> {
480
        let is_secure = BUILD_INFO.is_secure && !Policy::unsafe_skip();
×
481
        let init_response = InitResponse {
482
            is_secure,
483
            checksum: state.checksum,
×
484
            next_checksum: state.next_checksum,
×
485
            policy_checksum,
486
            rsk: state.signing_key,
×
487
            next_rsk: state.next_signing_key,
×
488
        };
489
        let signer: Arc<dyn Signer> = self.identity.clone();
×
490
        SignedInitResponse::new(init_response, &signer)
×
491
    }
492

493
    /// Authorize the remote enclave so that the private keys are never released to an incorrect enclave.
494
    fn authorize_private_key_generation(ctx: &RpcContext, runtime_id: &Namespace) -> Result<()> {
×
495
        if Policy::unsafe_skip() {
×
496
            return Ok(()); // Authorize unsafe builds always.
×
497
        }
498
        let remote_enclave = Self::authenticate(ctx)?;
×
499
        Policy::global().may_get_or_create_keys(remote_enclave, runtime_id)
×
500
    }
501

502
    /// Authorize the remote enclave so that the master and ephemeral secrets are never replicated
503
    /// to an incorrect enclave.
504
    fn authorize_secret_replication(ctx: &RpcContext) -> Result<()> {
×
505
        if Policy::unsafe_skip() {
×
506
            return Ok(()); // Authorize unsafe builds always.
×
507
        }
508
        let remote_enclave = Self::authenticate(ctx)?;
×
509
        Policy::global().may_replicate_secret(remote_enclave)
×
510
    }
511

512
    /// Authenticate the remote enclave based on the MRSIGNER/MRENCLAVE/request.
513
    fn authenticate(ctx: &RpcContext) -> Result<&EnclaveIdentity> {
×
514
        let si = ctx.session_info.as_ref();
×
515
        let si = si.ok_or(KeyManagerError::NotAuthenticated)?;
×
516
        Ok(&si.verified_quote.identity)
×
517
    }
518

519
    /// Fetch current epoch from the consensus layer.
520
    fn consensus_epoch(&self) -> Result<EpochTime> {
×
521
        let consensus_state = block_on(self.consensus_verifier.latest_state())?;
×
522
        let beacon_state = BeaconState::new(&consensus_state);
×
523
        let consensus_epoch = beacon_state.epoch()?;
×
524

525
        Ok(consensus_epoch)
×
526
    }
527

528
    /// Verify that the key manager status has been published in the consensus layer.
529
    fn validate_key_manager_status(&self, status: Status) -> Result<Status> {
×
530
        let consensus_verifier = self.consensus_verifier.clone();
×
531
        let verifier = PolicyVerifier::new(consensus_verifier);
×
532

533
        verifier.verify_key_manager_status(status, self.runtime_id)
×
534
    }
535

536
    /// Validate that the epoch used for derivation of ephemeral private keys is not
537
    /// in the future or too far back in the past.
538
    fn validate_ephemeral_key_epoch(&self, epoch: EpochTime) -> Result<()> {
×
539
        let consensus_epoch = self.consensus_epoch()?;
×
540
        if consensus_epoch < epoch || consensus_epoch > epoch + MAX_EPHEMERAL_KEY_AGE {
×
541
            return Err(KeyManagerError::InvalidEpoch(consensus_epoch, epoch).into());
×
542
        }
543
        Ok(())
×
544
    }
545

546
    /// Validate that given height is fresh, i.e. the height is not more than
547
    /// predefined number of blocks lower than the height of the latest trust root.
548
    ///
549
    /// Key manager should use this validation to detect whether the runtimes
550
    /// querying it have a fresh enough state.
551
    fn validate_height_freshness(&self, height: Option<u64>) -> Result<()> {
×
552
        // Outdated key manager clients will not send height in their requests.
553
        // To ensure backwards compatibility we skip check in those cases.
554
        // This should be removed in the future by making height mandatory.
555
        if let Some(height) = height {
×
556
            let latest_height = block_on(self.consensus_verifier.latest_height())?;
×
557
            if latest_height > MAX_FRESH_HEIGHT_AGE && height < latest_height - MAX_FRESH_HEIGHT_AGE
×
558
            {
559
                return Err(KeyManagerError::HeightNotFresh.into());
×
560
            }
561
        }
562
        Ok(())
×
563
    }
564

565
    /// Verify that the master secret has been published in the consensus layer.
566
    fn validate_signed_master_secret(
×
567
        &self,
568
        signed_secret: &SignedEncryptedMasterSecret,
569
    ) -> Result<EncryptedMasterSecret> {
570
        let consensus_state = block_on(self.consensus_verifier.latest_state())?;
×
571
        let km_state = KeyManagerState::new(&consensus_state);
×
572
        let published_signed_secret = km_state
×
573
            .master_secret(signed_secret.secret.runtime_id)?
×
574
            .filter(|published_signed_secret| published_signed_secret == signed_secret)
×
575
            .ok_or(KeyManagerError::MasterSecretNotPublished)?;
×
576

577
        Ok(published_signed_secret.secret)
×
578
    }
579

580
    /// Validate that the ephemeral secret has been published in the consensus layer.
581
    fn validate_signed_ephemeral_secret(
×
582
        &self,
583
        signed_secret: &SignedEncryptedEphemeralSecret,
584
    ) -> Result<EncryptedEphemeralSecret> {
585
        let consensus_state = block_on(self.consensus_verifier.latest_state())?;
×
586
        let km_state = KeyManagerState::new(&consensus_state);
×
587
        let published_signed_secret = km_state
×
588
            .ephemeral_secret(signed_secret.secret.runtime_id)?
×
589
            .filter(|published_signed_secret| published_signed_secret == signed_secret)
×
590
            .ok_or(KeyManagerError::EphemeralSecretNotPublished)?;
×
591

592
        Ok(published_signed_secret.secret)
×
593
    }
594

595
    /// Fetch the identities of the key manager nodes.
596
    fn key_manager_nodes(&self, id: Namespace) -> Result<Vec<signature::PublicKey>> {
×
597
        let consensus_state = block_on(self.consensus_verifier.latest_state())?;
×
598
        let km_state = KeyManagerState::new(&consensus_state);
×
599
        let status = km_state
×
600
            .status(id)?
×
601
            .ok_or(KeyManagerError::StatusNotFound)?;
×
602

603
        Ok(status.nodes)
×
604
    }
605

606
    /// Fetch REK keys of the key manager enclaves from the consensus layer.
607
    fn key_manager_rek_keys(
×
608
        &self,
609
        id: Namespace,
610
    ) -> Result<HashMap<signature::PublicKey, x25519::PublicKey>> {
611
        let nodes = self.key_manager_nodes(id)?;
×
612

613
        let consensus_state = block_on(self.consensus_verifier.latest_state())?;
×
614
        let registry_state = RegistryState::new(&consensus_state);
×
615

616
        let mut rek_map = HashMap::new();
×
617
        for pk in nodes.iter() {
×
618
            let node = registry_state.node(pk)?;
×
619
            let runtimes = node
×
620
                .map(|n| n.runtimes)
×
621
                .unwrap_or_default()
622
                .unwrap_or_default();
623
            // Skipping version check as key managers are running exactly one version of the runtime.
624
            let runtime = runtimes.iter().find(|nr| nr.id == id);
×
625

626
            let rek = if cfg!(any(target_env = "sgx", feature = "debug-mock-sgx")) {
627
                // In an SGX environment we use REK key from the consensus layer.
628
                runtime
NEW
629
                    .map(|nr| nr.capabilities.tee.as_ref())
×
630
                    .unwrap_or_default()
NEW
631
                    .map(|c| c.rek)
×
632
                    .unwrap_or_default()
633
            } else {
634
                // Otherwise we use the same insecure REK key for all enclaves.
NEW
635
                runtime.map(|_| self.identity.public_rek())
×
636
            };
637

638
            if let Some(rek) = rek {
×
639
                rek_map.insert(*pk, rek);
×
640
            }
641
        }
642

643
        Ok(rek_map)
×
644
    }
645

646
    /// Fetch the identities of the key manager nodes that can decrypt the given ephemeral secret.
647
    fn nodes_with_ephemeral_secret(
×
648
        &self,
649
        secret: &EncryptedEphemeralSecret,
650
    ) -> Result<Vec<signature::PublicKey>> {
651
        let rek_keys = self.key_manager_rek_keys(secret.runtime_id)?;
×
652
        let nodes = rek_keys
×
653
            .iter()
654
            .filter(|(_, rek)| secret.secret.ciphertexts.contains_key(rek))
×
655
            .map(|(&node, _)| node)
×
656
            .collect();
657

658
        Ok(nodes)
×
659
    }
660
}
661

662
impl Handler for Secrets {
663
    fn methods(&'static self) -> Vec<RpcMethod> {
×
664
        vec![
×
665
            // Register RPC methods exposed via EnclaveRPC to remote clients.
666
            RpcMethod::new(
×
667
                RpcMethodDescriptor {
×
668
                    name: METHOD_GET_OR_CREATE_KEYS.to_string(),
×
669
                    kind: RpcKind::NoiseSession,
×
670
                },
671
                move |ctx: &_, req: &_| self.get_or_create_keys(ctx, req),
×
672
            ),
673
            RpcMethod::new(
×
674
                RpcMethodDescriptor {
×
675
                    name: METHOD_GET_PUBLIC_KEY.to_string(),
×
676
                    kind: RpcKind::InsecureQuery,
×
677
                },
678
                move |_ctx: &_, req: &_| self.get_public_key(req),
×
679
            ),
680
            RpcMethod::new(
×
681
                RpcMethodDescriptor {
×
682
                    name: METHOD_GET_OR_CREATE_EPHEMERAL_KEYS.to_string(),
×
683
                    kind: RpcKind::NoiseSession,
×
684
                },
685
                move |ctx: &_, req: &_| self.get_or_create_ephemeral_keys(ctx, req),
×
686
            ),
687
            RpcMethod::new(
×
688
                RpcMethodDescriptor {
×
689
                    name: METHOD_GET_PUBLIC_EPHEMERAL_KEY.to_string(),
×
690
                    kind: RpcKind::InsecureQuery,
×
691
                },
692
                move |_ctx: &_, req: &_| self.get_public_ephemeral_key(req),
×
693
            ),
694
            RpcMethod::new(
×
695
                RpcMethodDescriptor {
×
696
                    name: METHOD_REPLICATE_MASTER_SECRET.to_string(),
×
697
                    kind: RpcKind::NoiseSession,
×
698
                },
699
                move |ctx: &_, req: &_| self.replicate_master_secret(ctx, req),
×
700
            ),
701
            RpcMethod::new(
×
702
                RpcMethodDescriptor {
×
703
                    name: METHOD_REPLICATE_EPHEMERAL_SECRET.to_string(),
×
704
                    kind: RpcKind::NoiseSession,
×
705
                },
706
                move |ctx: &_, req: &_| self.replicate_ephemeral_secret(ctx, req),
×
707
            ),
708
            // Register local methods, for use by the node key manager component.
709
            RpcMethod::new(
×
710
                RpcMethodDescriptor {
×
711
                    name: LOCAL_METHOD_INIT.to_string(),
×
712
                    kind: RpcKind::LocalQuery,
×
713
                },
714
                move |_ctx: &_, req: &_| self.init_kdf(req),
×
715
            ),
716
            RpcMethod::new(
×
717
                RpcMethodDescriptor {
×
718
                    name: LOCAL_METHOD_GENERATE_MASTER_SECRET.to_string(),
×
719
                    kind: RpcKind::LocalQuery,
×
720
                },
721
                move |_ctx: &_, req: &_| self.generate_master_secret(req),
×
722
            ),
723
            RpcMethod::new(
×
724
                RpcMethodDescriptor {
×
725
                    name: LOCAL_METHOD_GENERATE_EPHEMERAL_SECRET.to_string(),
×
726
                    kind: RpcKind::LocalQuery,
×
727
                },
728
                move |_ctx: &_, req: &_| self.generate_ephemeral_secret(req),
×
729
            ),
730
            RpcMethod::new(
×
731
                RpcMethodDescriptor {
×
732
                    name: LOCAL_METHOD_LOAD_MASTER_SECRET.to_string(),
×
733
                    kind: RpcKind::LocalQuery,
×
734
                },
735
                move |_ctx: &_, req: &_| self.load_master_secret(req),
×
736
            ),
737
            RpcMethod::new(
×
738
                RpcMethodDescriptor {
×
739
                    name: LOCAL_METHOD_LOAD_EPHEMERAL_SECRET.to_string(),
×
740
                    kind: RpcKind::LocalQuery,
×
741
                },
742
                move |_ctx: &_, req: &_| self.load_ephemeral_secret(req),
×
743
            ),
744
        ]
745
    }
746
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc