xref: /aosp_15_r20/system/authgraph/boringssl/src/test_device.rs (revision 4185b0660fbe514985fdcf75410317caad8afad1)
1*4185b066SAndroid Build Coastguard Worker // Copyright 2023 Google LLC
2*4185b066SAndroid Build Coastguard Worker //
3*4185b066SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*4185b066SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*4185b066SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*4185b066SAndroid Build Coastguard Worker //
7*4185b066SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
8*4185b066SAndroid Build Coastguard Worker //
9*4185b066SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*4185b066SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*4185b066SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*4185b066SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*4185b066SAndroid Build Coastguard Worker // limitations under the License.
14*4185b066SAndroid Build Coastguard Worker //
15*4185b066SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
16*4185b066SAndroid Build Coastguard Worker 
17*4185b066SAndroid Build Coastguard Worker //! An example implementation for the Authgraph `Device` trait for testing purposes.
18*4185b066SAndroid Build Coastguard Worker 
19*4185b066SAndroid Build Coastguard Worker use authgraph_core::{
20*4185b066SAndroid Build Coastguard Worker     ag_err,
21*4185b066SAndroid Build Coastguard Worker     error::Error,
22*4185b066SAndroid Build Coastguard Worker     key::{
23*4185b066SAndroid Build Coastguard Worker         AesKey, CertChain, EcSignKey, EcVerifyKey, Identity, IdentityVerificationDecision,
24*4185b066SAndroid Build Coastguard Worker         EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION, IDENTITY_VERSION,
25*4185b066SAndroid Build Coastguard Worker     },
26*4185b066SAndroid Build Coastguard Worker     traits,
27*4185b066SAndroid Build Coastguard Worker };
28*4185b066SAndroid Build Coastguard Worker use authgraph_wire::{ErrorCode, SESSION_ID_LEN};
29*4185b066SAndroid Build Coastguard Worker use core::cell::RefCell;
30*4185b066SAndroid Build Coastguard Worker use coset::{iana, CborOrdering};
31*4185b066SAndroid Build Coastguard Worker 
32*4185b066SAndroid Build Coastguard Worker /// The struct implementing the Authgraph `Device` trait.
33*4185b066SAndroid Build Coastguard Worker pub struct AgDevice {
34*4185b066SAndroid Build Coastguard Worker     per_boot_key: RefCell<Option<AesKey>>,
35*4185b066SAndroid Build Coastguard Worker     identity: RefCell<Option<(EcSignKey, Identity)>>,
36*4185b066SAndroid Build Coastguard Worker     cose_sign_algorithm: RefCell<Option<iana::Algorithm>>,
37*4185b066SAndroid Build Coastguard Worker     // Make the (source/sink) version configurable for testing purposes
38*4185b066SAndroid Build Coastguard Worker     version: RefCell<i32>,
39*4185b066SAndroid Build Coastguard Worker }
40*4185b066SAndroid Build Coastguard Worker 
41*4185b066SAndroid Build Coastguard Worker impl Default for AgDevice {
default() -> Self42*4185b066SAndroid Build Coastguard Worker     fn default() -> Self {
43*4185b066SAndroid Build Coastguard Worker         AgDevice {
44*4185b066SAndroid Build Coastguard Worker             per_boot_key: RefCell::new(None),
45*4185b066SAndroid Build Coastguard Worker             identity: RefCell::new(None),
46*4185b066SAndroid Build Coastguard Worker             cose_sign_algorithm: RefCell::new(None),
47*4185b066SAndroid Build Coastguard Worker             version: RefCell::new(1),
48*4185b066SAndroid Build Coastguard Worker         }
49*4185b066SAndroid Build Coastguard Worker     }
50*4185b066SAndroid Build Coastguard Worker }
51*4185b066SAndroid Build Coastguard Worker 
52*4185b066SAndroid Build Coastguard Worker impl AgDevice {
53*4185b066SAndroid Build Coastguard Worker     /// Set the given identity
set_identity( &self, identity: (EcSignKey, Identity), cose_sign_algorithm: iana::Algorithm, )54*4185b066SAndroid Build Coastguard Worker     pub fn set_identity(
55*4185b066SAndroid Build Coastguard Worker         &self,
56*4185b066SAndroid Build Coastguard Worker         identity: (EcSignKey, Identity),
57*4185b066SAndroid Build Coastguard Worker         cose_sign_algorithm: iana::Algorithm,
58*4185b066SAndroid Build Coastguard Worker     ) {
59*4185b066SAndroid Build Coastguard Worker         *self.identity.borrow_mut() = Some(identity);
60*4185b066SAndroid Build Coastguard Worker         *self.cose_sign_algorithm.borrow_mut() = Some(cose_sign_algorithm);
61*4185b066SAndroid Build Coastguard Worker     }
62*4185b066SAndroid Build Coastguard Worker }
63*4185b066SAndroid Build Coastguard Worker 
64*4185b066SAndroid Build Coastguard Worker impl traits::Device for AgDevice {
get_or_create_per_boot_key( &self, aes: &dyn traits::AesGcm, rng: &mut dyn traits::Rng, ) -> Result<AesKey, Error>65*4185b066SAndroid Build Coastguard Worker     fn get_or_create_per_boot_key(
66*4185b066SAndroid Build Coastguard Worker         &self,
67*4185b066SAndroid Build Coastguard Worker         aes: &dyn traits::AesGcm,
68*4185b066SAndroid Build Coastguard Worker         rng: &mut dyn traits::Rng,
69*4185b066SAndroid Build Coastguard Worker     ) -> Result<AesKey, Error> {
70*4185b066SAndroid Build Coastguard Worker         if self.per_boot_key.borrow().is_none() {
71*4185b066SAndroid Build Coastguard Worker             let pbk = aes.generate_key(rng)?;
72*4185b066SAndroid Build Coastguard Worker             *self.per_boot_key.borrow_mut() = Some(pbk);
73*4185b066SAndroid Build Coastguard Worker         }
74*4185b066SAndroid Build Coastguard Worker         self.per_boot_key
75*4185b066SAndroid Build Coastguard Worker             .borrow()
76*4185b066SAndroid Build Coastguard Worker             .as_ref()
77*4185b066SAndroid Build Coastguard Worker             .cloned()
78*4185b066SAndroid Build Coastguard Worker             .ok_or(ag_err!(InternalError, "per boot key cannot be none at this point"))
79*4185b066SAndroid Build Coastguard Worker     }
80*4185b066SAndroid Build Coastguard Worker 
get_per_boot_key(&self) -> Result<AesKey, Error>81*4185b066SAndroid Build Coastguard Worker     fn get_per_boot_key(&self) -> Result<AesKey, Error> {
82*4185b066SAndroid Build Coastguard Worker         self.per_boot_key
83*4185b066SAndroid Build Coastguard Worker             .borrow()
84*4185b066SAndroid Build Coastguard Worker             .as_ref()
85*4185b066SAndroid Build Coastguard Worker             .cloned()
86*4185b066SAndroid Build Coastguard Worker             .ok_or(ag_err!(InternalError, "per boot key is missing"))
87*4185b066SAndroid Build Coastguard Worker     }
88*4185b066SAndroid Build Coastguard Worker 
89*4185b066SAndroid Build Coastguard Worker     /// If the `identity` field is not set (e.g. via `set_identity`), the default implementation
90*4185b066SAndroid Build Coastguard Worker     /// creates identity with a ExplicitKeyDiceCertChain that only contains a
91*4185b066SAndroid Build Coastguard Worker     /// DiceCertChainInitialPayload (i.e. no DiceChainEntry) and without a policy.
92*4185b066SAndroid Build Coastguard Worker     /// DiceCertChainInitialPayload is an EC public key on P-256 curve in the default implementation
get_identity(&self) -> Result<(Option<EcSignKey>, Identity), Error>93*4185b066SAndroid Build Coastguard Worker     fn get_identity(&self) -> Result<(Option<EcSignKey>, Identity), Error> {
94*4185b066SAndroid Build Coastguard Worker         if self.identity.borrow().is_none() {
95*4185b066SAndroid Build Coastguard Worker             let (priv_key, mut pub_key) = crate::ec::create_p256_key_pair(iana::Algorithm::ES256)?;
96*4185b066SAndroid Build Coastguard Worker             pub_key.canonicalize(CborOrdering::Lexicographic);
97*4185b066SAndroid Build Coastguard Worker             let identity = Identity {
98*4185b066SAndroid Build Coastguard Worker                 version: IDENTITY_VERSION,
99*4185b066SAndroid Build Coastguard Worker                 cert_chain: CertChain {
100*4185b066SAndroid Build Coastguard Worker                     version: EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION,
101*4185b066SAndroid Build Coastguard Worker                     root_key: EcVerifyKey::P256(pub_key),
102*4185b066SAndroid Build Coastguard Worker                     dice_cert_chain: None,
103*4185b066SAndroid Build Coastguard Worker                 },
104*4185b066SAndroid Build Coastguard Worker                 policy: None,
105*4185b066SAndroid Build Coastguard Worker             };
106*4185b066SAndroid Build Coastguard Worker             self.set_identity((EcSignKey::P256(priv_key), identity), iana::Algorithm::ES256);
107*4185b066SAndroid Build Coastguard Worker         }
108*4185b066SAndroid Build Coastguard Worker         let (sign_key, identity) = self
109*4185b066SAndroid Build Coastguard Worker             .identity
110*4185b066SAndroid Build Coastguard Worker             .borrow()
111*4185b066SAndroid Build Coastguard Worker             .as_ref()
112*4185b066SAndroid Build Coastguard Worker             .cloned()
113*4185b066SAndroid Build Coastguard Worker             .ok_or(ag_err!(InternalError, "identity is missing"))?;
114*4185b066SAndroid Build Coastguard Worker         Ok((Some(sign_key), identity))
115*4185b066SAndroid Build Coastguard Worker     }
116*4185b066SAndroid Build Coastguard Worker 
get_cose_sign_algorithm(&self) -> Result<iana::Algorithm, Error>117*4185b066SAndroid Build Coastguard Worker     fn get_cose_sign_algorithm(&self) -> Result<iana::Algorithm, Error> {
118*4185b066SAndroid Build Coastguard Worker         self.cose_sign_algorithm
119*4185b066SAndroid Build Coastguard Worker             .borrow()
120*4185b066SAndroid Build Coastguard Worker             .as_ref()
121*4185b066SAndroid Build Coastguard Worker             .cloned()
122*4185b066SAndroid Build Coastguard Worker             .ok_or(ag_err!(InternalError, "cose sign algorithm is missing"))
123*4185b066SAndroid Build Coastguard Worker     }
124*4185b066SAndroid Build Coastguard Worker 
sign_data(&self, _ecdsa: &dyn traits::EcDsa, _data: &[u8]) -> Result<Vec<u8>, Error>125*4185b066SAndroid Build Coastguard Worker     fn sign_data(&self, _ecdsa: &dyn traits::EcDsa, _data: &[u8]) -> Result<Vec<u8>, Error> {
126*4185b066SAndroid Build Coastguard Worker         // Since the private signing key is returned in the `get_identity` method of this test
127*4185b066SAndroid Build Coastguard Worker         // implementation of the `device` trait, and therefore we can use `EcDsa::sign` method, this
128*4185b066SAndroid Build Coastguard Worker         // method is marked as `Unimplemented`.
129*4185b066SAndroid Build Coastguard Worker         Err(ag_err!(Unimplemented, "unexpected signing request when the signing key available"))
130*4185b066SAndroid Build Coastguard Worker     }
131*4185b066SAndroid Build Coastguard Worker 
evaluate_identity( &self, _latest_identity: &Identity, _previous_identity: &Identity, ) -> Result<IdentityVerificationDecision, Error>132*4185b066SAndroid Build Coastguard Worker     fn evaluate_identity(
133*4185b066SAndroid Build Coastguard Worker         &self,
134*4185b066SAndroid Build Coastguard Worker         _latest_identity: &Identity,
135*4185b066SAndroid Build Coastguard Worker         _previous_identity: &Identity,
136*4185b066SAndroid Build Coastguard Worker     ) -> Result<IdentityVerificationDecision, Error> {
137*4185b066SAndroid Build Coastguard Worker         // TODO (b/304623554): this trait method is not used in the key exchange protocol. This will
138*4185b066SAndroid Build Coastguard Worker         // be implemented in the next phase of AuthGraph
139*4185b066SAndroid Build Coastguard Worker         Err(ag_err!(Unimplemented, ""))
140*4185b066SAndroid Build Coastguard Worker     }
141*4185b066SAndroid Build Coastguard Worker 
get_version(&self) -> i32142*4185b066SAndroid Build Coastguard Worker     fn get_version(&self) -> i32 {
143*4185b066SAndroid Build Coastguard Worker         *self.version.borrow()
144*4185b066SAndroid Build Coastguard Worker     }
145*4185b066SAndroid Build Coastguard Worker 
get_negotiated_version(&self, peer_version: i32) -> i32146*4185b066SAndroid Build Coastguard Worker     fn get_negotiated_version(&self, peer_version: i32) -> i32 {
147*4185b066SAndroid Build Coastguard Worker         let self_version = *self.version.borrow();
148*4185b066SAndroid Build Coastguard Worker         if peer_version < self_version {
149*4185b066SAndroid Build Coastguard Worker             return peer_version;
150*4185b066SAndroid Build Coastguard Worker         }
151*4185b066SAndroid Build Coastguard Worker         self_version
152*4185b066SAndroid Build Coastguard Worker     }
153*4185b066SAndroid Build Coastguard Worker 
record_shared_sessions( &mut self, _peer_identity: &Identity, _session_id: &[u8; SESSION_ID_LEN], _shared_keys: &[Vec<u8>; 2], _sha256: &dyn traits::Sha256, ) -> Result<(), Error>154*4185b066SAndroid Build Coastguard Worker     fn record_shared_sessions(
155*4185b066SAndroid Build Coastguard Worker         &mut self,
156*4185b066SAndroid Build Coastguard Worker         _peer_identity: &Identity,
157*4185b066SAndroid Build Coastguard Worker         _session_id: &[u8; SESSION_ID_LEN],
158*4185b066SAndroid Build Coastguard Worker         _shared_keys: &[Vec<u8>; 2],
159*4185b066SAndroid Build Coastguard Worker         _sha256: &dyn traits::Sha256,
160*4185b066SAndroid Build Coastguard Worker     ) -> Result<(), Error> {
161*4185b066SAndroid Build Coastguard Worker         // The test implementation does not need to store the shared keys because there is no
162*4185b066SAndroid Build Coastguard Worker         // application protocol to run using the shared keys.
163*4185b066SAndroid Build Coastguard Worker         Ok(())
164*4185b066SAndroid Build Coastguard Worker     }
165*4185b066SAndroid Build Coastguard Worker 
validate_shared_sessions( &self, _peer_identity: &Identity, _session_id: &[u8; SESSION_ID_LEN], _shared_keys: &[Vec<u8>], _sha256: &dyn traits::Sha256, ) -> Result<(), Error>166*4185b066SAndroid Build Coastguard Worker     fn validate_shared_sessions(
167*4185b066SAndroid Build Coastguard Worker         &self,
168*4185b066SAndroid Build Coastguard Worker         _peer_identity: &Identity,
169*4185b066SAndroid Build Coastguard Worker         _session_id: &[u8; SESSION_ID_LEN],
170*4185b066SAndroid Build Coastguard Worker         _shared_keys: &[Vec<u8>],
171*4185b066SAndroid Build Coastguard Worker         _sha256: &dyn traits::Sha256,
172*4185b066SAndroid Build Coastguard Worker     ) -> Result<(), Error> {
173*4185b066SAndroid Build Coastguard Worker         // The test implementation does not need to validate the shared keys because there is no
174*4185b066SAndroid Build Coastguard Worker         // application protocol that depends on the shared keys.
175*4185b066SAndroid Build Coastguard Worker         Ok(())
176*4185b066SAndroid Build Coastguard Worker     }
177*4185b066SAndroid Build Coastguard Worker }
178*4185b066SAndroid Build Coastguard Worker 
179*4185b066SAndroid Build Coastguard Worker impl AgDevice {
180*4185b066SAndroid Build Coastguard Worker     /// Make the version configurable for testing purposes
set_version(&self, version: i32)181*4185b066SAndroid Build Coastguard Worker     pub fn set_version(&self, version: i32) {
182*4185b066SAndroid Build Coastguard Worker         *self.version.borrow_mut() = version
183*4185b066SAndroid Build Coastguard Worker     }
184*4185b066SAndroid Build Coastguard Worker }
185