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