• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2025 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16 
17 //! Data structures used in AuthMgr Backend
18 use crate::{
19     am_err,
20     error::{Error, ErrorCode},
21     traits::RawConnection,
22 };
23 use alloc::boxed::Box;
24 use alloc::collections::VecDeque;
25 use alloc::sync::Arc;
26 use alloc::vec::Vec;
27 use authgraph_core::key::{CertChain, EcVerifyKey, InstanceIdentifier, Policy};
28 use authmgr_common::{
29     signed_connection_request::{Challenge, TransportID},
30     Token,
31 };
32 use log::warn;
33 
34 /// Version of the data structure format used to store details of a persistent instance
35 pub const VERSION_PERSISTENT_INSTANCE_CONTEXT: i32 = 1;
36 /// Version of the data structure format used to store details of a persistent client
37 pub const VERSION_PERSISTENT_CLIENT_CONTEXT: i32 = 1;
38 
39 /// Default value for maximum number of entries in the cache for authentication started pVMs
40 pub const MAX_SIZE_AUTH_STARTED_PVMS: usize = 6;
41 /// Default value for maximum number of entries in the cache for authenticated pVMs
42 pub const MAX_SIZE_AUTH_COMPLETED_PVMS: usize = 6;
43 /// Default value for the maximum number of entries in the cache for authorized clients
44 /// per connection
45 pub const MAX_AUTHORIZED_CLIENTS_PER_CONNECTION: usize = 8;
46 
47 /// Type alias for a client identifier of 64 bytes. This identifier is assigned by the pVM.
48 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
49 pub struct ClientId(pub Vec<u8>);
50 
51 /// Information stored in an authenticated connection established between a pVM and the AuthMgr BE.
52 /// This information is re-used when serving multiple requests for authorizing the
53 /// clients in the pVM
54 pub struct AuthenticatedConnectionState {
55     /// Instance id of the pvm
56     pub instance_id: Arc<InstanceIdentifier>,
57     /// Transport id of the pvm
58     pub transport_id: TransportID,
59     /// Unique sequence number assigned to the instance by the AuthMgr BE
60     pub instance_seq_number: i32,
61     /// DICE artifacts of the pvm
62     pub dice_artifacts: DiceArtifacts,
63     /// Public key of the signing key pair of the pvm
64     pub pub_signing_key: EcVerifyKey,
65     /// Whether the pvm is persistent
66     pub is_persistent: bool,
67     /// Maximum number of clients allowed for the pvm
68     pub max_num_of_clients: usize,
69     /// Cache of the authorized clients of the pvm
70     pub authorized_clients: Vec<AuthorizedClient>,
71 }
72 
73 impl AuthenticatedConnectionState {
74     /// Populate the information to be stored in-memory in the connection state
new( instance_id: Arc<InstanceIdentifier>, transport_id: TransportID, instance_seq_number: i32, dice_artifacts: DiceArtifacts, pub_signing_key: EcVerifyKey, is_persistent: bool, max_num_of_clients: usize, ) -> Result<Self, Error>75     pub fn new(
76         instance_id: Arc<InstanceIdentifier>,
77         transport_id: TransportID,
78         instance_seq_number: i32,
79         dice_artifacts: DiceArtifacts,
80         pub_signing_key: EcVerifyKey,
81         is_persistent: bool,
82         max_num_of_clients: usize,
83     ) -> Result<Self, Error> {
84         let mut authorized_clients = Vec::<AuthorizedClient>::new();
85         authorized_clients.try_reserve(max_num_of_clients)?;
86         Ok(Self {
87             instance_id,
88             transport_id,
89             instance_seq_number,
90             dice_artifacts,
91             pub_signing_key,
92             is_persistent,
93             max_num_of_clients,
94             authorized_clients,
95         })
96     }
97 
98     /// Given the client id, get the id information of the corresponding authorized client.
get_mutable_authorized_client( &mut self, client_id: &ClientId, ) -> Option<&mut AuthorizedClient>99     pub fn get_mutable_authorized_client(
100         &mut self,
101         client_id: &ClientId,
102     ) -> Option<&mut AuthorizedClient> {
103         self.authorized_clients.iter_mut().find(|client| *client.client_id == *client_id)
104     }
105 
106     /// Insert the authorized client into into the cache
insert_authorized_client( &mut self, authorized_client: AuthorizedClient, ) -> Result<(), Error>107     pub fn insert_authorized_client(
108         &mut self,
109         authorized_client: AuthorizedClient,
110     ) -> Result<(), Error> {
111         if self
112             .authorized_clients
113             .iter()
114             .any(|client| client.sequence_number == authorized_client.sequence_number)
115         {
116             return Err(am_err!(
117                 InternalError,
118                 "a client with the given sequence number already exist in the cache"
119             ));
120         }
121         if self.authorized_clients.len() == self.max_num_of_clients {
122             return Err(am_err!(
123                 MemoryAllocationFailed,
124                 "Max limit for the authorized clients per connection reached."
125             ));
126         }
127         self.authorized_clients.push(authorized_client);
128         Ok(())
129     }
130 }
131 
132 /// Encapsulation of the DICE certificate chain and the DICE policy used to validate it
133 #[derive(Clone)]
134 pub struct DiceArtifacts {
135     /// DICE certificate chain
136     pub cert_chain: Arc<CertChain>,
137     /// DICE poicy
138     pub policy: Arc<Policy>,
139 }
140 
141 /// Information associated with an authorized client. This information is used to check for
142 /// duplicate authorization attempts for the same client.
143 #[derive(Clone)]
144 pub struct AuthorizedClient {
145     /// Client id
146     pub client_id: Arc<ClientId>,
147     /// Unique sequence number assigned to the client by the AuthMgr BE
148     pub sequence_number: i32,
149     /// DICE policy of the client
150     pub policy: Arc<Policy>,
151 }
152 
153 impl AuthorizedClient {
154     /// Update the client's policy with the given policy
update_policy(&mut self, updated_policy: &Arc<Policy>)155     pub fn update_policy(&mut self, updated_policy: &Arc<Policy>) {
156         self.policy = Arc::clone(updated_policy);
157     }
158 }
159 
160 /// Information of a persistent pvm instance stored in the persistent secure storage.
161 /// Deletion of the persistent instances (and clients) at runtime is not currently supported.
162 #[derive(Clone)]
163 pub struct PersistentInstanceContext {
164     /// Version of the data structure format
165     pub version: i32,
166     /// Unique sequence number of the persistent instance
167     pub sequence_number: i32,
168     /// DICE policy
169     pub dice_policy: Arc<Policy>,
170 }
171 
172 /// Information of a persistent client stored in the persistent secure storage.
173 #[derive(Clone)]
174 pub struct PersistentClientContext {
175     /// Version of the data structure format
176     pub version: i32,
177     /// Unique sequence number of the persistent client
178     pub sequence_number: i32,
179     /// DICE policy
180     pub dice_policy: Arc<Policy>,
181 }
182 
183 /// Encapsulates information about a pVM instance which has completed step 1 of phase 1 of the
184 /// AuthMgr protocol  (i.e. `init_authentication`), but not step 2 (i.e. `complete_authentication`).
185 #[derive(Clone, PartialEq)]
186 pub struct AuthStartedPvm {
187     /// Transport id of the pvm (a.k.a. VM ID)
188     pub transport_id: TransportID,
189     /// Instance id of the pvm
190     pub instance_id: Arc<InstanceIdentifier>,
191     /// Challenge issued by the AuthMgr BE to this pvm
192     pub challenge: Challenge,
193     /// Certificate chain of the pvm
194     pub cert_chain: Arc<CertChain>,
195 }
196 
197 impl AuthStartedPvm {
198     /// Perform state transition of an AuthStartedPvm.
mark_as_authenticated( &self, auth_started_pvms: &mut AuthStartedPvms, authenticated_pvms: &mut AuthenticatedPvms, ) -> Result<(), Error>199     pub fn mark_as_authenticated(
200         &self,
201         auth_started_pvms: &mut AuthStartedPvms,
202         authenticated_pvms: &mut AuthenticatedPvms,
203     ) -> Result<(), Error> {
204         // Remove any other entries in `AuthStartedPvms` with the authenticated instance id, to
205         // enforce the Trust On First Use (TOFU) principle.
206         auth_started_pvms.remove_via_instance_id(&self.instance_id);
207         authenticated_pvms.insert(self)
208     }
209 }
210 
211 /// A list of pVMs which have initiated authentication, but not have completed authentication.
212 pub struct AuthStartedPvms {
213     /// The number of allowed authentication started pvms at a given time
214     capacity: usize,
215     /// The list of authentication started pvms
216     auth_started_pvms: VecDeque<AuthStartedPvm>,
217 }
218 
219 impl AuthStartedPvms {
220     /// Constructor
new(capacity: usize) -> Result<Self, Error>221     pub fn new(capacity: usize) -> Result<Self, Error> {
222         let mut auth_started_pvms = VecDeque::new();
223         auth_started_pvms.try_reserve(capacity)?;
224         Ok(AuthStartedPvms { capacity, auth_started_pvms })
225     }
226 
227     /// Insert a new entry to the list
insert(&mut self, auth_started_pvm: AuthStartedPvm)228     pub fn insert(&mut self, auth_started_pvm: AuthStartedPvm) {
229         if self.auth_started_pvms.len() == self.capacity {
230             // Here we remove the oldest entry instead of returning an error in order to prevent
231             // genuine pvms from being denied from starting authentication due to `AuthStartedPvms`
232             // being filled up to the capacity - which can be caused by both malicious activity and
233             // non-malicious activity (e.g. a pvm starts authentication, but never completes).
234             warn!("Maximum number of auth started pvms reached. Removing the oldest one.");
235             self.auth_started_pvms.pop_front();
236         }
237         self.auth_started_pvms.push_back(auth_started_pvm);
238     }
239 
240     /// Check if an entry with a given transport id already exists in the list - this is used to
241     /// prevent duplicated authentication attempts from the same instance.
has_transport_id(&self, transport_id: TransportID) -> bool242     pub fn has_transport_id(&self, transport_id: TransportID) -> bool {
243         self.auth_started_pvms.iter().any(|entry| entry.transport_id == transport_id)
244     }
245 
246     /// Take an entry out of the list via its transport id - this is used to retrieve the required
247     /// information to perform step 2 of phase 1 for those who have performed step 1 of phase 1.
take_via_transport_id(&mut self, transport_id: TransportID) -> Option<AuthStartedPvm>248     pub fn take_via_transport_id(&mut self, transport_id: TransportID) -> Option<AuthStartedPvm> {
249         let index =
250             self.auth_started_pvms.iter().position(|entry| entry.transport_id == transport_id);
251         index.map(|index| self.auth_started_pvms.remove(index))?
252     }
253 
254     /// Remove an entry via its transport id - this is used to remove an entry when only the
255     /// transport id is available - e.g. upon connection close.
remove_via_transport_id(&mut self, transport_id: TransportID)256     pub fn remove_via_transport_id(&mut self, transport_id: TransportID) {
257         self.auth_started_pvms.retain(|entry| entry.transport_id != transport_id);
258     }
259 
260     /// Remove all entries with a given instance id - this is used to remove all entries with
261     /// an authenticated instance id.
remove_via_instance_id(&mut self, instance_id: &InstanceIdentifier)262     pub fn remove_via_instance_id(&mut self, instance_id: &InstanceIdentifier) {
263         self.auth_started_pvms.retain(|entry| &*entry.instance_id != instance_id);
264     }
265 }
266 
267 /// Encapsulates information about a pVM instance which has completed phase 1 of the AuthMgr
268 /// protocol
269 #[derive(PartialEq)]
270 pub struct AuthenticatedPvm {
271     /// Instance id of the pvm
272     pub instance_id: Arc<InstanceIdentifier>,
273     /// Transport id of the pvm
274     pub transport_id: TransportID,
275 }
276 
277 /// A list of pVMs which have completed authentication
278 pub struct AuthenticatedPvms {
279     /// The number of allowed authentication completed pvms at a given time
280     capacity: usize,
281     /// List of authentication completed pvms
282     authenticated_pvms: Vec<AuthenticatedPvm>,
283 }
284 
285 impl AuthenticatedPvms {
286     /// Constructor
new(capacity: usize) -> Result<Self, Error>287     pub fn new(capacity: usize) -> Result<Self, Error> {
288         let mut authenticated_pvms = Vec::<AuthenticatedPvm>::new();
289         authenticated_pvms.try_reserve(capacity)?;
290         Ok(AuthenticatedPvms { capacity, authenticated_pvms })
291     }
292 
293     /// Insert a new entry to the list, constructed from the given AuthStartedPvm
insert(&mut self, auth_started_pvm: &AuthStartedPvm) -> Result<(), Error>294     pub fn insert(&mut self, auth_started_pvm: &AuthStartedPvm) -> Result<(), Error> {
295         if self.authenticated_pvms.len() == self.capacity {
296             return Err(am_err!(
297                 MemoryAllocationFailed,
298                 "Maximum number of authenticated pvms reached."
299             ));
300         }
301         let authenticated_pvm = AuthenticatedPvm {
302             instance_id: Arc::clone(&auth_started_pvm.instance_id),
303             transport_id: auth_started_pvm.transport_id,
304         };
305         self.authenticated_pvms.push(authenticated_pvm);
306         Ok(())
307     }
308 
309     /// Check if a pvm with a given instance id already exists in the list - this is used to prevent
310     /// duplicated authentication attempts
has_instance_id(&self, instance_id: &InstanceIdentifier) -> bool311     pub fn has_instance_id(&self, instance_id: &InstanceIdentifier) -> bool {
312         self.authenticated_pvms.iter().any(|entry| &*entry.instance_id == instance_id)
313     }
314 
315     /// Check if a pvm with a given transport id already exists in the list - this is used to
316     /// ensure that step 1 of phase 2 of the AuthMgr protocol is allowed only for already
317     /// authenticated instances
has_transport_id(&self, transport_id: TransportID) -> bool318     pub fn has_transport_id(&self, transport_id: TransportID) -> bool {
319         self.authenticated_pvms.iter().any(|entry| entry.transport_id == transport_id)
320     }
321 
322     /// Remove a pvm instance via its transport id (upon connection close)
remove_via_transport_id(&mut self, transport_id: TransportID)323     pub fn remove_via_transport_id(&mut self, transport_id: TransportID) {
324         self.authenticated_pvms.retain(|entry| entry.transport_id != transport_id);
325     }
326 }
327 
328 /// The in-memory data structure representing a new connection requested for a client in step 1 of
329 /// phase 2 of the AuthMgr protocol. The token is used to authorize this new connection.
330 /// The same token should be sent over an already authenticated connection setup between AuthMgr FE
331 /// and AuthMgr BE.
332 pub struct PendingClientAuthorization {
333     /// Token used to authorize a connection
334     pub token: Token,
335     /// Client connection
336     pub client_connection: Box<dyn RawConnection>,
337 }
338 
339 impl PendingClientAuthorization {
340     /// Constructor for a pending client authorization
new(token: Token, client_connection: Box<dyn RawConnection>) -> Self341     pub fn new(token: Token, client_connection: Box<dyn RawConnection>) -> Self {
342         PendingClientAuthorization { token, client_connection }
343     }
344 }
345 
346 /// The in-memory data structure to keep track of the new connections requested by a particular pVM
347 /// (identified by the transport id), on behalf of a client. The limit for the number of connections
348 /// allowed per pVM should be specified when initializing the AuthMgr BE.
349 pub struct PendingClientAuthorizationsPerPvm {
350     /// Transport id of the pvm
351     transport_id: TransportID,
352     /// List of authentication completed pvms
353     capacity: usize,
354     /// A list of client connections pending authorization
355     pending_clients: Vec<PendingClientAuthorization>,
356 }
357 
358 impl PendingClientAuthorizationsPerPvm {
359     /// Constructor
new(transport_id: TransportID, capacity: usize) -> Result<Self, Error>360     pub fn new(transport_id: TransportID, capacity: usize) -> Result<Self, Error> {
361         let mut pending_clients = Vec::<PendingClientAuthorization>::new();
362         pending_clients.try_reserve(capacity)?;
363         Ok(PendingClientAuthorizationsPerPvm { transport_id, capacity, pending_clients })
364     }
365 
366     /// Insert a new entry to the list
insert( &mut self, pending_client_authorization: PendingClientAuthorization, ) -> Result<(), Error>367     pub fn insert(
368         &mut self,
369         pending_client_authorization: PendingClientAuthorization,
370     ) -> Result<(), Error> {
371         if self.pending_clients.len() == self.capacity {
372             return Err(am_err!(
373                 MemoryAllocationFailed,
374                 "Maximum capacity reached for the pending authorizations for the pVM with the
375                  transport id: {:?}.",
376                 self.transport_id
377             ));
378         }
379         if self
380             .pending_clients
381             .iter()
382             .any(|client| client.token == pending_client_authorization.token)
383         {
384             return Err(am_err!(
385                 InternalError,
386                 "a pending client authorzation with the given tokan already exists"
387             ));
388         }
389         self.pending_clients.push(pending_client_authorization);
390         Ok(())
391     }
392 
393     /// Take an entry out of the list, given the token
take(&mut self, token: Token) -> Option<PendingClientAuthorization>394     pub fn take(&mut self, token: Token) -> Option<PendingClientAuthorization> {
395         let index = self
396             .pending_clients
397             .iter()
398             .position(|pending_authorization| pending_authorization.token == token);
399         index.map(|index| self.pending_clients.remove(index))
400     }
401 }
402 
403 /// The in-memory data structure that stores the new connections requested from different pVMs
404 /// on behalf of the clients, to be authorized and handed over to the trusted services.
405 /// The limit for the number of entries should be the same as the limit for the authenticated pVMs.
406 /// We use a separate data structure rather than using `AuthenticatedPvms` or `AuthenticatedPvm`
407 /// because at the time the requests for initiating a new connection for a client comes in,
408 /// we do not know whether it is coming from an "authenticated AuthMgr FE component" in the pVM.
409 pub struct PendingClientAuthorizations {
410     /// The allowed number of pvms
411     capacity: usize,
412     /// The allowed number of pending connections per pvm
413     max_entries_per_pvm: usize,
414     /// List of pending client connections categorized by pvm
415     pending_clients_by_pvm: Vec<PendingClientAuthorizationsPerPvm>,
416 }
417 
418 impl PendingClientAuthorizations {
419     /// Constructor for PendingClientAuthorizations
new(capacity: usize, max_entries_per_pvm: usize) -> Result<Self, Error>420     pub fn new(capacity: usize, max_entries_per_pvm: usize) -> Result<Self, Error> {
421         let mut pending_clients_by_pvm = Vec::<PendingClientAuthorizationsPerPvm>::new();
422         pending_clients_by_pvm.try_reserve(capacity)?;
423         Ok(PendingClientAuthorizations { capacity, max_entries_per_pvm, pending_clients_by_pvm })
424     }
425 
426     /// Insert a pending client authorization
insert( &mut self, transport_id: TransportID, pending_client_authorization: PendingClientAuthorization, ) -> Result<(), Error>427     pub fn insert(
428         &mut self,
429         transport_id: TransportID,
430         pending_client_authorization: PendingClientAuthorization,
431     ) -> Result<(), Error> {
432         let per_pvm_entry: Option<&mut PendingClientAuthorizationsPerPvm> =
433             self.pending_clients_by_pvm.iter_mut().find(|entry| entry.transport_id == transport_id);
434         match per_pvm_entry {
435             Some(per_pvm_entry) => {
436                 per_pvm_entry.insert(pending_client_authorization)?;
437             }
438             None => {
439                 if self.pending_clients_by_pvm.len() == self.capacity {
440                     return Err(am_err!(
441                         MemoryAllocationFailed,
442                         "Maximum capacity reached for the number of pVMs that can accept
443                          pending authorizations."
444                     ));
445                 }
446                 let mut pending_clients_for_pvm =
447                     PendingClientAuthorizationsPerPvm::new(transport_id, self.max_entries_per_pvm)?;
448                 pending_clients_for_pvm.insert(pending_client_authorization)?;
449                 self.pending_clients_by_pvm.push(pending_clients_for_pvm);
450             }
451         }
452         Ok(())
453     }
454 
455     /// Take the pending client authorization that matches the transport id and the token
take( &mut self, transport_id: TransportID, token: Token, ) -> Option<PendingClientAuthorization>456     pub fn take(
457         &mut self,
458         transport_id: TransportID,
459         token: Token,
460     ) -> Option<PendingClientAuthorization> {
461         self.pending_clients_by_pvm
462             .iter_mut()
463             .find(|per_pvm_list| per_pvm_list.transport_id == transport_id)
464             .map(|pending_authorizations_per_pvm| pending_authorizations_per_pvm.take(token))?
465     }
466 
467     /// Remove all the connections identified by the transport id
remove_via_transport_id(&mut self, transport_id: TransportID)468     pub fn remove_via_transport_id(&mut self, transport_id: TransportID) {
469         self.pending_clients_by_pvm
470             .retain(|pending_clients_per_pvm| pending_clients_per_pvm.transport_id != transport_id);
471     }
472 }
473 
474 /// Encapsulation of the full DICE artifacts of a client. This is particularly required for the
475 /// "policy matching as a service" provided by AuthMgr BE.
476 pub struct AuthorizedClientFullDiceArtifacts {
477     /// Unique sequence number of the client
478     pub sequence_number: i32,
479     /// Transport id of the pvm that the client belongs to (used to cleanup the cache upon
480     /// connection close by the pvm)
481     pub transport_id: TransportID,
482     /// Client's id (used to cleanup the cache upon client deletion)
483     pub client_id: Arc<ClientId>,
484     /// Complete DICE artifacts of the client
485     pub full_dice_artifacts: DiceArtifacts,
486 }
487 
488 /// List of authorized clients with their full DICE artifacts. This is particularly required for the
489 /// "policy matching as a service" provided by AuthMgr BE.
490 pub struct AuthorizedClientsGlobalList {
491     /// Allowed number of authorized clients
492     capacity: usize,
493     /// List of authorized clients with their complete set of DICE artifacts (i.e. the leaf DICE
494     /// artifacts combined with the pvm DICE artifacts)
495     authorized_clients_list: Vec<AuthorizedClientFullDiceArtifacts>,
496 }
497 
498 impl AuthorizedClientsGlobalList {
499     /// Constructor
new(capacity: usize) -> Result<Self, Error>500     pub fn new(capacity: usize) -> Result<Self, Error> {
501         let mut authorized_clients_list = Vec::<AuthorizedClientFullDiceArtifacts>::new();
502         authorized_clients_list.try_reserve(capacity)?;
503         Ok(AuthorizedClientsGlobalList { capacity, authorized_clients_list })
504     }
505 
506     /// Retrieve a mutable client given the client's unique sequence number
get_mut(&mut self, seq_number: i32) -> Option<&mut AuthorizedClientFullDiceArtifacts>507     pub fn get_mut(&mut self, seq_number: i32) -> Option<&mut AuthorizedClientFullDiceArtifacts> {
508         self.authorized_clients_list
509             .iter_mut()
510             .find(|authorized_client| authorized_client.sequence_number == seq_number)
511     }
512 
513     /// Insert a new entry to the list
insert( &mut self, authorized_client_full_dice_artifacts: AuthorizedClientFullDiceArtifacts, ) -> Result<(), Error>514     pub fn insert(
515         &mut self,
516         authorized_client_full_dice_artifacts: AuthorizedClientFullDiceArtifacts,
517     ) -> Result<(), Error> {
518         if self.authorized_clients_list.iter().any(|authorized_client| {
519             authorized_client.sequence_number
520                 == authorized_client_full_dice_artifacts.sequence_number
521         }) {
522             return Err(am_err!(
523                 InternalError,
524                 "full  dice artifacts already exists for the unique client sequence number: {:?}.",
525                 authorized_client_full_dice_artifacts.sequence_number
526             ));
527         }
528         if self.authorized_clients_list.len() == self.capacity {
529             return Err(am_err!(
530                 MemoryAllocationFailed,
531                 "Capacity for the global list of authorized clients reached."
532             ));
533         }
534         self.authorized_clients_list.push(authorized_client_full_dice_artifacts);
535         Ok(())
536     }
537 
538     /// Remove all entries given a transport id
remove_via_transport_id(&mut self, transport_id: TransportID)539     pub fn remove_via_transport_id(&mut self, transport_id: TransportID) {
540         self.authorized_clients_list
541             .retain(|authorized_clients| authorized_clients.transport_id != transport_id);
542     }
543 
544     /// Remove an entry given the client id
remove_via_client_id(&mut self, client_id: &ClientId)545     pub fn remove_via_client_id(&mut self, client_id: &ClientId) {
546         self.authorized_clients_list
547             .retain(|authorized_clients| *authorized_clients.client_id == *client_id);
548     }
549 }
550 
551 /// Max sizes of the in-memory data structures to be specified by the implementation of
552 /// the AuthMgrBE. These numbers may depend on the max number of connections supported by the TEE
553 /// per process.
554 pub struct MemoryLimits {
555     /// Capacity of the AuthStartedPvms list
556     pub capacity_auth_started_pvms: usize,
557     /// Capacity of the AuthCompletedPvms list
558     pub capacity_auth_completed_pvms: usize,
559     /// Number of clients allowed per pvm
560     pub max_clients_per_pvm: usize,
561 }
562 
563 impl Default for MemoryLimits {
default() -> Self564     fn default() -> Self {
565         Self {
566             capacity_auth_started_pvms: MAX_SIZE_AUTH_STARTED_PVMS,
567             capacity_auth_completed_pvms: MAX_SIZE_AUTH_COMPLETED_PVMS,
568             max_clients_per_pvm: MAX_AUTHORIZED_CLIENTS_PER_CONNECTION,
569         }
570     }
571 }
572