• 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 //! Reference implementation of the `IAuthMgrAuthorization.aidl` for the AuthMgr Backend.
18 // TODO: remove this
19 #![allow(dead_code)]
20 use crate::{
21     am_err,
22     data_structures::{
23         AuthStartedPvm, AuthStartedPvms, AuthenticatedConnectionState, AuthenticatedPvms,
24         AuthorizedClient, AuthorizedClientFullDiceArtifacts, AuthorizedClientsGlobalList, ClientId,
25         DiceArtifacts, MemoryLimits, PendingClientAuthorization, PendingClientAuthorizations,
26         PersistentClientContext, PersistentInstanceContext, VERSION_PERSISTENT_CLIENT_CONTEXT,
27         VERSION_PERSISTENT_INSTANCE_CONTEXT,
28     },
29     error::{Error, ErrorCode},
30     traits::{CryptoTraitImpl, Device, PersistentStorage, RawConnection, RpcConnection},
31     try_to_vec,
32 };
33 use alloc::boxed::Box;
34 use alloc::sync::Arc;
35 use authgraph_core::key::{CertChain, DiceChainEntry, InstanceIdentifier, Policy};
36 use authmgr_common::{
37     extend_dice_policy_with, match_dice_cert_with_policy, match_dice_chain_with_policy,
38     signed_connection_request::{Challenge, ConnectionRequest},
39     Token,
40 };
41 use coset::CborSerializable;
42 
43 /// Data structure encapsulating AuthMgr backend.
44 /// Note that we assume the use of AuthMgrBE in single threaded environments. It is planned for the
45 /// future to make AuthMgrBE usable in multi-threaded environments b/369207531 and to make all
46 /// allocations fallible b/401550040.
47 pub struct AuthMgrBE {
48     crypto: CryptoTraitImpl,
49     device: Box<dyn Device>,
50     persistent_storage: Box<dyn PersistentStorage>,
51     auth_started_pvms: AuthStartedPvms,
52     auth_completed_pvms: AuthenticatedPvms,
53     latest_global_sequence_number: LatestGlobalSeqNum,
54     pending_client_authorizations: PendingClientAuthorizations,
55     authorized_clients: AuthorizedClientsGlobalList,
56     memory_limits: MemoryLimits,
57 }
58 
59 /// Data structure encapsulating the global sequence number - which is used to assign a unique
60 /// identifier to the instances and clients by the AuthMgr BE
61 pub struct LatestGlobalSeqNum(i32);
62 
63 impl LatestGlobalSeqNum {
64     /// Constructs an instance of the in-memory global sequence number given the latest global
65     /// sequence number which is read from the persistent storage
new(latest_global_seq_num: i32) -> Self66     pub fn new(latest_global_seq_num: i32) -> Self {
67         Self(latest_global_seq_num)
68     }
69 
70     /// Return the current global sequence number and increment the global sequence number in the
71     /// persistent storage and in this in-memory instance
fetch_and_increment( &mut self, persistent_storage: &mut dyn PersistentStorage, ) -> Result<i32, Error>72     pub fn fetch_and_increment(
73         &mut self,
74         persistent_storage: &mut dyn PersistentStorage,
75     ) -> Result<i32, Error> {
76         let current_global_seq_num = self.0;
77         self.0 = persistent_storage.increment_global_sequence_number()?;
78         Ok(current_global_seq_num)
79     }
80 }
81 
82 impl AuthMgrBE {
83     /// Initialize AuthMgr BE
new( crypto: CryptoTraitImpl, device: Box<dyn Device>, mut persistent_storage: Box<dyn PersistentStorage>, memory_limits: MemoryLimits, ) -> Result<Self, Error>84     pub fn new(
85         crypto: CryptoTraitImpl,
86         device: Box<dyn Device>,
87         mut persistent_storage: Box<dyn PersistentStorage>,
88         memory_limits: MemoryLimits,
89     ) -> Result<Self, Error> {
90         let auth_started_pvms = AuthStartedPvms::new(memory_limits.capacity_auth_started_pvms)?;
91         let auth_completed_pvms =
92             AuthenticatedPvms::new(memory_limits.capacity_auth_completed_pvms)?;
93         let pending_client_authorizations = PendingClientAuthorizations::new(
94             memory_limits.capacity_auth_completed_pvms,
95             memory_limits.max_clients_per_pvm,
96         )?;
97         let authorized_clients = AuthorizedClientsGlobalList::new(
98             memory_limits.capacity_auth_completed_pvms * memory_limits.max_clients_per_pvm,
99         )?;
100         // If this is the first time the AuthMgr BE is running after the first boot of the device,
101         // initialize the global sequence number, otherwise, read it from the AuthMgr BE's storage
102         let latest_global_sequence_number =
103             LatestGlobalSeqNum(persistent_storage.get_or_create_global_sequence_number()?);
104         Ok(AuthMgrBE {
105             crypto,
106             device,
107             persistent_storage,
108             auth_started_pvms,
109             auth_completed_pvms,
110             latest_global_sequence_number,
111             pending_client_authorizations,
112             authorized_clients,
113             memory_limits,
114         })
115     }
116 
117     /// Step 1 of phase 1
init_authentication( &mut self, connection: &dyn RpcConnection, cert_chain: &[u8], ext_instance_id: Option<&[u8]>, ) -> Result<Challenge, Error>118     pub fn init_authentication(
119         &mut self,
120         connection: &dyn RpcConnection,
121         cert_chain: &[u8],
122         ext_instance_id: Option<&[u8]>,
123     ) -> Result<Challenge, Error> {
124         // Check if the connection is already authenticated by retrieving the connection state
125         if connection.get_authenticated_state()?.is_some() {
126             return Err(am_err!(
127                 InstanceAlreadyAuthenticated,
128                 "connection is already authenticated"
129             ));
130         }
131 
132         // Retrieve the transport ID
133         let transport_id = connection.get_peer_transport_id()?;
134 
135         // Decode the DICE certificate chain
136         let cert_chain = CertChain::from_slice(cert_chain)
137             .map_err(|_e| am_err!(InvalidDiceCertChain, "failed to decode the DICE cert chain."))?;
138 
139         // First, extract the instance identifier from the DICE chain. Only if it is not present,
140         // check if a valid instance identifier is provided via the optional parameter
141         let instance_id: InstanceIdentifier =
142             match cert_chain.extract_instance_identifier_in_guest_os_entry()? {
143                 Some(id) => id,
144                 None => ext_instance_id.map(|id| id.to_vec()).ok_or(am_err!(
145                     InvalidInstanceIdentifier,
146                     "Instance identifier is neither present in the DICE cert chain,
147                         nor in the optional argument"
148                 ))?,
149             };
150 
151         // Check for duplicated authentication attempts.
152         // We check with the instance id and transport id separately, and not with the combination
153         // of the two, because the latter allows the same pVM to be spawned twice (resulting in two
154         // different transport ids and the same instance id) and connected, which we want to avoid.
155         if self.auth_completed_pvms.has_instance_id(&instance_id) {
156             return Err(am_err!(
157                 InstanceAlreadyAuthenticated,
158                 "duplicated authentication attempt with the instance id: {:?}!",
159                 instance_id
160             ));
161         }
162         if self.auth_completed_pvms.has_transport_id(transport_id) {
163             return Err(am_err!(
164                 InstanceAlreadyAuthenticated,
165                 "duplicated authentication attempt with the transport id: {:?}!",
166                 transport_id
167             ));
168         }
169         // We filter duplicated entries in `AuthStartedPvms` via the transport id only.
170         // We do not filter via instance id here in order to prevent a potental DoS attack where an
171         // impersonating pVM starts authentication with a genuine pVM's instance id, but never
172         // completes.
173         if self.auth_started_pvms.has_transport_id(transport_id) {
174             return Err(am_err!(
175                 AuthenticationAlreadyStarted,
176                 "duplicated attempt to start authentication!"
177             ));
178         }
179         let mut challenge = [0; 32];
180         self.crypto.rng.fill_bytes(&mut challenge);
181         // TODO: b/401550040. Use fallible allocation when Rust supports it.
182         self.auth_started_pvms.insert(AuthStartedPvm {
183             transport_id,
184             instance_id: Arc::new(instance_id),
185             challenge,
186             cert_chain: Arc::new(cert_chain),
187         });
188         Ok(challenge)
189     }
190 
191     /// Step 2 of phase 1
complete_authentication( &mut self, connection: &mut dyn RpcConnection, signed_response: &[u8], dice_policy: &[u8], ) -> Result<(), Error>192     pub fn complete_authentication(
193         &mut self,
194         connection: &mut dyn RpcConnection,
195         signed_response: &[u8],
196         dice_policy: &[u8],
197     ) -> Result<(), Error> {
198         // Check if the connection is already authenticated by retrieving the connection state
199         if connection.get_authenticated_state()?.is_some() {
200             return Err(am_err!(
201                 InstanceAlreadyAuthenticated,
202                 "connection is already authenticated"
203             ));
204         }
205 
206         // Retrieve the transport ID
207         let peer_transport_id = connection.get_peer_transport_id()?;
208         // Check for duplicated authentication attempts to enforce Trust On First Use (TOFU).
209         if self.auth_completed_pvms.has_transport_id(peer_transport_id) {
210             return Err(am_err!(
211                 InstanceAlreadyAuthenticated,
212                 "duplicated authentication attempt!"
213             ));
214         }
215         let auth_started_entry =
216             self.auth_started_pvms.take_via_transport_id(peer_transport_id).ok_or(am_err!(
217                 AuthenticationNotStarted,
218                 "An authentication started pVM was not found for the given transport id"
219             ))?;
220         if self.auth_completed_pvms.has_instance_id(&auth_started_entry.instance_id) {
221             return Err(am_err!(
222                 InstanceAlreadyAuthenticated,
223                 "duplicated authentication attempt!"
224             ));
225         }
226         // Validate the DICE cert chain and retrieve the signature verification key
227         let sig_verification_key =
228             (*auth_started_entry.cert_chain).validate(&*self.crypto.ecdsa).map_err(|_e| {
229                 am_err!(InvalidDiceCertChain, "failed to validate the DICE cert chain.")
230             })?;
231 
232         // Authenticate the client by validating their signature on the response to the challenge.
233         // Construct the expected `ConnectionRequest` CBOR structure as the payload of the signature
234         let expected_conn_req = ConnectionRequest::new_for_ffa_transport(
235             auth_started_entry.challenge,
236             peer_transport_id,
237             self.device.get_self_transport_id()?,
238         );
239         expected_conn_req
240             .verify(signed_response, &sig_verification_key, &*self.crypto.ecdsa)
241             .map_err(|_e| {
242                 am_err!(
243                     SignatureVerificationFailed,
244                     "failed to verify signature on the connection request"
245                 )
246             })?;
247 
248         let given_dice_policy = Arc::new(Policy(try_to_vec(dice_policy)?));
249         let is_persistent = self.device.is_persistent_instance(&auth_started_entry.instance_id)?;
250         let instance_seq_number = if is_persistent {
251             self.handle_instance_in_persistent_storage(
252                 &auth_started_entry.instance_id,
253                 &given_dice_policy,
254                 &auth_started_entry.cert_chain,
255             )?
256         } else {
257             // TODO: b/399707150
258             return Err(am_err!(Unimplemented, "Non persistent instances are not yet supported."));
259         };
260         // Construct the connection state
261         let connection_state = AuthenticatedConnectionState::new(
262             Arc::clone(&auth_started_entry.instance_id),
263             auth_started_entry.transport_id,
264             instance_seq_number,
265             DiceArtifacts {
266                 cert_chain: Arc::clone(&auth_started_entry.cert_chain),
267                 policy: given_dice_policy,
268             },
269             sig_verification_key,
270             is_persistent,
271             self.memory_limits.max_clients_per_pvm,
272         )?;
273         connection.store_authenticated_state(connection_state)?;
274         auth_started_entry
275             .mark_as_authenticated(&mut self.auth_started_pvms, &mut self.auth_completed_pvms)?;
276         Ok(())
277     }
278 
279     /// Step 1 of phase 2
280     /// A new connection should be used for client authorization. The AuthMgr-BE TA implementation
281     /// should make sure that it fails gracefully, if a connection that is already used for instance
282     /// authentication is attempted to be used for client authorization.
init_connection_for_client( &mut self, client_connection: Box<dyn RawConnection>, token: Token, ) -> Result<(), Error>283     pub fn init_connection_for_client(
284         &mut self,
285         client_connection: Box<dyn RawConnection>,
286         token: Token,
287     ) -> Result<(), Error> {
288         // Check if this request comes from a pVM which has an AuthMgr FE that is already
289         // authenticated with the AuthMgr BE.
290         let client_transport_id = client_connection.get_peer_transport_id()?;
291         if !self.auth_completed_pvms.has_transport_id(client_transport_id) {
292             return Err(am_err!(
293                 InstanceNotAuthenticated,
294                 "the transport id is not associated with a pVM that has an
295                   authenticated AuthMgr FE."
296             ));
297         }
298 
299         // Add the connection and the token to the pending client authorization list.
300         self.pending_client_authorizations
301             .insert(client_transport_id, PendingClientAuthorization { token, client_connection })?;
302         Ok(())
303     }
304 
305     /// Step 2 of phase 2
authorize_and_connect_client_to_trusted_service( &mut self, connection: &mut dyn RpcConnection, client_id: &[u8], service_name: &str, token: Token, client_dice_cert: &[u8], client_dice_policy: &[u8], ) -> Result<(), Error>306     pub fn authorize_and_connect_client_to_trusted_service(
307         &mut self,
308         connection: &mut dyn RpcConnection,
309         client_id: &[u8],
310         service_name: &str,
311         token: Token,
312         client_dice_cert: &[u8],
313         client_dice_policy: &[u8],
314     ) -> Result<(), Error> {
315         // Check whether the connection is already authenticated.
316         let state = connection.get_mutable_authenticated_state()?.ok_or(am_err!(
317             ConnectionNotAuthenticated,
318             "phase 2 of the AuthMgr protocol can only be invoked on an authenticated connection."
319         ))?;
320         // Retrieve the new connection corresponding to this request from pending authorizations
321         let pending_authorization =
322             self.pending_client_authorizations.take(state.transport_id, token).ok_or(am_err!(
323                 NoConnectionToAuthorize,
324                 "no pending authorization found for the transport id: {:?} and token: {:?}",
325                 state.transport_id,
326                 token
327             ))?;
328 
329         let client_id = Arc::new(ClientId(try_to_vec(client_id)?));
330         let given_policy = Arc::new(Policy(try_to_vec(client_dice_policy)?));
331         let given_dice_cert = DiceChainEntry::from_slice(client_dice_cert)?;
332         let is_persistent = state.is_persistent;
333         let instance_seq_number = state.instance_seq_number;
334         // In what follows, we do the following:
335         // 1. Read from the cache to see if this client is already authorized in the current boot
336         //    cycle of the pVM instance. If the client is in the cache, enforce rollback protection
337         //    for the client in the cache. This includes running the dice chain to policy matching
338         //    checks and if they are successful, updating both the storage and the cache if the
339         //    policy has been updated.
340         // 2. If the client is not in the cache, read the client context from the storage.
341         //    a) If the client context is in the storage, enforce rollback protection for the client
342         //       in the storage.
343         //    b) If the client is not in the stroge, create the instance context in the storage.
344         //    c) Insert the client into the cache.
345         let mut authorized_client = state.get_mutable_authorized_client(&client_id);
346         let (client_seq_number, policy_need_update) = match authorized_client {
347             Some(ref mut client) => {
348                 let client_seq_number = client.sequence_number;
349                 let policy_need_update = !(given_policy == client.policy);
350                 self.enforce_rollback_protection_for_client_in_cache(
351                     instance_seq_number,
352                     is_persistent,
353                     client,
354                     &given_dice_cert,
355                     &given_policy,
356                 )?;
357                 (client_seq_number, policy_need_update)
358             }
359             None => {
360                 // If not, read from the storage
361                 let client_seq_number = if is_persistent {
362                     self.handle_client_in_persistent_storage(
363                         instance_seq_number,
364                         &client_id,
365                         &given_dice_cert,
366                         &given_policy,
367                     )?
368                 } else {
369                     // TODO: b/399707150
370                     return Err(am_err!(
371                         Unimplemented,
372                         "Non persistent instances are not yet supported."
373                     ));
374                 };
375                 // Insert into the cache
376                 state.insert_authorized_client(AuthorizedClient {
377                     client_id: Arc::clone(&client_id),
378                     sequence_number: client_seq_number,
379                     policy: Arc::clone(&given_policy),
380                 })?;
381                 (client_seq_number, false)
382             }
383         };
384         // Update the cache containing the global list of authorized clients with their full DICE
385         // artifacts to be used by the "policy matching as a service" offered by AuthMgr-BE
386         self.update_global_list_of_authorized_clients(
387             state,
388             client_seq_number,
389             &client_id,
390             &given_dice_cert,
391             &given_policy,
392             policy_need_update,
393         )?;
394         // Handover the authorized client to the requested trusted service
395         // TODO: Upon successful handover, update the connected services for the client in the cache
396         // and the storage, if needed
397         self.device.handover_client_connection(
398             service_name,
399             client_seq_number,
400             pending_authorization.client_connection,
401             is_persistent,
402         )
403     }
404 
405     /// This should be called by the TEE environment upon closing of every connection established
406     /// between AuthMgr FE and AuthMgr BE "for the purpose of authenticating AuthMgr FE
407     /// to AuthMgr BE" - i.e. the connections established in phase 1, in order to clear the cache.
clear_cache_upon_main_connection_close( &mut self, connection: &mut dyn RpcConnection, ) -> Result<(), Error>408     pub fn clear_cache_upon_main_connection_close(
409         &mut self,
410         connection: &mut dyn RpcConnection,
411     ) -> Result<(), Error> {
412         let transport_id = connection.get_peer_transport_id()?;
413         self.auth_started_pvms.remove_via_transport_id(transport_id);
414         self.auth_completed_pvms.remove_via_transport_id(transport_id);
415         self.pending_client_authorizations.remove_via_transport_id(transport_id);
416         self.authorized_clients.remove_via_transport_id(transport_id);
417         connection.remove_authenticated_state()?;
418         Ok(())
419     }
420 
421     // A helper method for creating/updating the instance context in the secure storage and
422     // enforcing rollback protection for a persistent pvm.
handle_instance_in_persistent_storage( &mut self, instance_id: &Arc<InstanceIdentifier>, given_policy: &Arc<Policy>, dice_chain: &CertChain, ) -> Result<i32, Error>423     fn handle_instance_in_persistent_storage(
424         &mut self,
425         instance_id: &Arc<InstanceIdentifier>,
426         given_policy: &Arc<Policy>,
427         dice_chain: &CertChain,
428     ) -> Result<i32, Error> {
429         match self.persistent_storage.read_instance_context(instance_id)? {
430             Some(instance_ctx) => {
431                 self.enforce_rollback_protection_for_pvm(
432                     instance_id,
433                     given_policy,
434                     &instance_ctx.dice_policy,
435                     dice_chain,
436                     true,
437                 )?;
438                 Ok(instance_ctx.sequence_number)
439             }
440             None => {
441                 if !match_dice_chain_with_policy(dice_chain, given_policy)? {
442                     return Err(am_err!(
443                         DicePolicyMatchingFailed,
444                         "the DICE chain doesn't match the given DICE policy."
445                     ));
446                 }
447                 if !self.device.is_persistent_instance_creation_allowed(instance_id, dice_chain)? {
448                     return Err(am_err!(
449                         InstanceContextCreationDenied,
450                         "the given persistent instance cannot be created"
451                     ));
452                 }
453                 let sequence_number = self
454                     .latest_global_sequence_number
455                     .fetch_and_increment(&mut *self.persistent_storage)?;
456                 self.persistent_storage.create_instance_context(
457                     instance_id,
458                     PersistentInstanceContext {
459                         version: VERSION_PERSISTENT_INSTANCE_CONTEXT,
460                         sequence_number,
461                         dice_policy: Arc::clone(given_policy),
462                     },
463                 )?;
464                 Ok(sequence_number)
465             }
466         }
467     }
468 
469     // A helper function for enforcing rollback protection on a pvm instance.
enforce_rollback_protection_for_pvm( &mut self, instance_id: &Arc<InstanceIdentifier>, given_policy: &Arc<Policy>, stored_policy: &Policy, dice_chain: &CertChain, is_persistent: bool, ) -> Result<(), Error>470     fn enforce_rollback_protection_for_pvm(
471         &mut self,
472         instance_id: &Arc<InstanceIdentifier>,
473         given_policy: &Arc<Policy>,
474         stored_policy: &Policy,
475         dice_chain: &CertChain,
476         is_persistent: bool,
477     ) -> Result<(), Error> {
478         // First, match the given policy and the dice chain
479         if !match_dice_chain_with_policy(dice_chain, given_policy)? {
480             return Err(am_err!(
481                 DicePolicyMatchingFailed,
482                 "the DICE chain doesn't match the given DICE policy."
483             ));
484         }
485         if *stored_policy != **given_policy {
486             if !match_dice_chain_with_policy(dice_chain, stored_policy)? {
487                 return Err(am_err!(
488                     DicePolicyMatchingFailed,
489                     "the DICE chain doesn't match the stored DICE policy."
490                 ));
491             }
492             if is_persistent {
493                 self.persistent_storage
494                     .update_instance_policy_in_storage(instance_id, given_policy)?;
495             } else {
496                 // TODO: b/399707150
497                 return Err(am_err!(
498                     Unimplemented,
499                     "Non persistent instances are not yet supported."
500                 ));
501             }
502         }
503         Ok(())
504     }
505 
506     // A helper method to enforce rollback protection for a client already in the cache.
enforce_rollback_protection_for_client_in_cache( &mut self, instance_seq_number: i32, is_persistent: bool, authorized_client: &mut AuthorizedClient, given_dice_cert: &DiceChainEntry, given_policy: &Arc<Policy>, ) -> Result<(), Error>507     fn enforce_rollback_protection_for_client_in_cache(
508         &mut self,
509         instance_seq_number: i32,
510         is_persistent: bool,
511         authorized_client: &mut AuthorizedClient,
512         given_dice_cert: &DiceChainEntry,
513         given_policy: &Arc<Policy>,
514     ) -> Result<(), Error> {
515         self.enforce_rollback_protection_for_client(
516             instance_seq_number,
517             &authorized_client.client_id,
518             given_dice_cert,
519             given_policy,
520             &authorized_client.policy,
521             is_persistent,
522         )?;
523         if *authorized_client.policy != **given_policy {
524             // Update the policy in the cache as well
525             authorized_client.update_policy(given_policy);
526         }
527         Ok(())
528     }
529 
handle_client_in_persistent_storage( &mut self, instance_seq_number: i32, client_id: &Arc<ClientId>, given_dice_cert: &DiceChainEntry, given_policy: &Arc<Policy>, ) -> Result<i32, Error>530     fn handle_client_in_persistent_storage(
531         &mut self,
532         instance_seq_number: i32,
533         client_id: &Arc<ClientId>,
534         given_dice_cert: &DiceChainEntry,
535         given_policy: &Arc<Policy>,
536     ) -> Result<i32, Error> {
537         match self.persistent_storage.read_client_context(instance_seq_number, client_id)? {
538             Some(client_ctx) => {
539                 self.enforce_rollback_protection_for_client(
540                     instance_seq_number,
541                     client_id,
542                     given_dice_cert,
543                     given_policy,
544                     &client_ctx.dice_policy,
545                     true,
546                 )?;
547                 Ok(client_ctx.sequence_number)
548             }
549             None => {
550                 if !match_dice_cert_with_policy(given_dice_cert, given_policy)? {
551                     return Err(am_err!(
552                         DicePolicyMatchingFailed,
553                         "the client's DICE leaf certificate doesn't match the given DICE policy"
554                     ));
555                 }
556                 let sequence_number = self
557                     .latest_global_sequence_number
558                     .fetch_and_increment(&mut *self.persistent_storage)?;
559                 self.persistent_storage.create_client_context(
560                     instance_seq_number,
561                     client_id,
562                     PersistentClientContext {
563                         version: VERSION_PERSISTENT_CLIENT_CONTEXT,
564                         sequence_number,
565                         dice_policy: Arc::clone(given_policy),
566                     },
567                 )?;
568                 Ok(sequence_number)
569             }
570         }
571     }
572 
enforce_rollback_protection_for_client( &mut self, instance_seq_number: i32, client_id: &Arc<ClientId>, given_dice_cert: &DiceChainEntry, given_policy: &Arc<Policy>, stored_policy: &Policy, is_persistent: bool, ) -> Result<(), Error>573     fn enforce_rollback_protection_for_client(
574         &mut self,
575         instance_seq_number: i32,
576         client_id: &Arc<ClientId>,
577         given_dice_cert: &DiceChainEntry,
578         given_policy: &Arc<Policy>,
579         stored_policy: &Policy,
580         is_persistent: bool,
581     ) -> Result<(), Error> {
582         // First, match the given policy and the DICE certificate
583         if !match_dice_cert_with_policy(given_dice_cert, given_policy)? {
584             return Err(am_err!(
585                 DicePolicyMatchingFailed,
586                 "the client's DICE leaf certificate doesn't match the given DICE policy"
587             ));
588         }
589         if **given_policy != *stored_policy {
590             if !match_dice_cert_with_policy(given_dice_cert, stored_policy)? {
591                 return Err(am_err!(
592                     DicePolicyMatchingFailed,
593                     "the client's DICE leaf certificate doesn't match the stored DICE policy"
594                 ));
595             }
596             // Update the policy in the storage
597             if is_persistent {
598                 self.persistent_storage.update_client_policy_in_storage(
599                     instance_seq_number,
600                     client_id,
601                     given_policy,
602                 )?;
603             } else {
604                 // TODO: b/399707150
605                 return Err(am_err!(
606                     Unimplemented,
607                     "Non persistent instances are not yet supported."
608                 ));
609             }
610         }
611         Ok(())
612     }
613 
614     // We need to update the cache containing the global list of authorized clients with
615     // their full DICE artifacts to be used in the service exposed by the AuthMgr BE to the
616     // trusted services for matching DICE chain and DICE policies of the clients.
update_global_list_of_authorized_clients( &mut self, state: &AuthenticatedConnectionState, client_seq_number: i32, client_id: &Arc<ClientId>, dice_leaf: &DiceChainEntry, given_policy: &Arc<Policy>, policy_need_update: bool, ) -> Result<(), Error>617     fn update_global_list_of_authorized_clients(
618         &mut self,
619         state: &AuthenticatedConnectionState,
620         client_seq_number: i32,
621         client_id: &Arc<ClientId>,
622         dice_leaf: &DiceChainEntry,
623         given_policy: &Arc<Policy>,
624         policy_need_update: bool,
625     ) -> Result<(), Error> {
626         match self.authorized_clients.get_mut(client_seq_number) {
627             Some(ref mut authorized_client) => {
628                 if !authorized_client.full_dice_artifacts.cert_chain.is_current_leaf(dice_leaf) {
629                     // This state is possible only if the client's DICE cert can change in runtime
630                     // e.g. (loadable TAs)
631                     let updated_full_dice_chain = (*state.dice_artifacts.cert_chain)
632                         .extend_with(dice_leaf, &*self.crypto.ecdsa)?;
633                     authorized_client.full_dice_artifacts.cert_chain =
634                         Arc::new(updated_full_dice_chain);
635                 }
636 
637                 if policy_need_update {
638                     authorized_client.full_dice_artifacts.policy = Arc::new(
639                         extend_dice_policy_with(&state.dice_artifacts.policy, given_policy)?,
640                     );
641                 }
642             }
643             None => {
644                 let client_full_dice_artifacts = DiceArtifacts {
645                     cert_chain: Arc::new(
646                         (*state.dice_artifacts.cert_chain)
647                             .extend_with(dice_leaf, &*self.crypto.ecdsa)?,
648                     ),
649                     policy: Arc::new(extend_dice_policy_with(
650                         &state.dice_artifacts.policy,
651                         given_policy,
652                     )?),
653                 };
654 
655                 self.authorized_clients.insert(AuthorizedClientFullDiceArtifacts {
656                     sequence_number: client_seq_number,
657                     transport_id: state.transport_id,
658                     client_id: Arc::clone(client_id),
659                     full_dice_artifacts: client_full_dice_artifacts,
660                 })?;
661             }
662         }
663         Ok(())
664     }
665 }
666