xref: /aosp_15_r20/system/secretkeeper/client/src/lib.rs (revision 3f8e9d82f4020c68ad19a99fc5fdc1fc90b79379)
1*3f8e9d82SAndroid Build Coastguard Worker // Copyright 2023, The Android Open Source Project
2*3f8e9d82SAndroid Build Coastguard Worker //
3*3f8e9d82SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*3f8e9d82SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*3f8e9d82SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*3f8e9d82SAndroid Build Coastguard Worker //
7*3f8e9d82SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*3f8e9d82SAndroid Build Coastguard Worker //
9*3f8e9d82SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*3f8e9d82SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*3f8e9d82SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*3f8e9d82SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*3f8e9d82SAndroid Build Coastguard Worker // limitations under the License.
14*3f8e9d82SAndroid Build Coastguard Worker 
15*3f8e9d82SAndroid Build Coastguard Worker //! This library is a stub for Secretkeeper, which can be used by clients. It exposes
16*3f8e9d82SAndroid Build Coastguard Worker //! Secretkeeper Session which can be used for using the SecretManagement API.
17*3f8e9d82SAndroid Build Coastguard Worker //! It encapsulates the Cryptography! AuthgraphKeyExchange is triggered on creation of a session
18*3f8e9d82SAndroid Build Coastguard Worker //! and the messages is encrypted/decrypted using the shared keys.
19*3f8e9d82SAndroid Build Coastguard Worker 
20*3f8e9d82SAndroid Build Coastguard Worker mod authgraph_dev;
21*3f8e9d82SAndroid Build Coastguard Worker pub mod dice;
22*3f8e9d82SAndroid Build Coastguard Worker 
23*3f8e9d82SAndroid Build Coastguard Worker use crate::authgraph_dev::AgDevice;
24*3f8e9d82SAndroid Build Coastguard Worker use crate::dice::OwnedDiceArtifactsWithExplicitKey;
25*3f8e9d82SAndroid Build Coastguard Worker 
26*3f8e9d82SAndroid Build Coastguard Worker use authgraph_boringssl as boring;
27*3f8e9d82SAndroid Build Coastguard Worker use authgraph_core::keyexchange as ke;
28*3f8e9d82SAndroid Build Coastguard Worker use authgraph_core::key;
29*3f8e9d82SAndroid Build Coastguard Worker use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper
30*3f8e9d82SAndroid Build Coastguard Worker     ::ISecretkeeper::ISecretkeeper;
31*3f8e9d82SAndroid Build Coastguard Worker use android_hardware_security_authgraph::aidl::android::hardware::security::authgraph::{
32*3f8e9d82SAndroid Build Coastguard Worker     IAuthGraphKeyExchange::IAuthGraphKeyExchange, PlainPubKey::PlainPubKey, PubKey::PubKey,
33*3f8e9d82SAndroid Build Coastguard Worker     SessionIdSignature::SessionIdSignature, Identity::Identity,
34*3f8e9d82SAndroid Build Coastguard Worker };
35*3f8e9d82SAndroid Build Coastguard Worker use coset::{CoseKey, CborSerializable, CoseEncrypt0};
36*3f8e9d82SAndroid Build Coastguard Worker use secretkeeper_core::cipher;
37*3f8e9d82SAndroid Build Coastguard Worker use secretkeeper_comm::data_types::SeqNum;
38*3f8e9d82SAndroid Build Coastguard Worker use secretkeeper_comm::wire::ApiError;
39*3f8e9d82SAndroid Build Coastguard Worker use std::cell::RefCell;
40*3f8e9d82SAndroid Build Coastguard Worker use std::fmt;
41*3f8e9d82SAndroid Build Coastguard Worker use std::rc::Rc;
42*3f8e9d82SAndroid Build Coastguard Worker 
43*3f8e9d82SAndroid Build Coastguard Worker /// A Secretkeeper session that can be used by client, this encapsulates the Authgraph Key exchange
44*3f8e9d82SAndroid Build Coastguard Worker /// session as well as the encryption/decryption of request/response to/from Secretkeeper.
45*3f8e9d82SAndroid Build Coastguard Worker pub struct SkSession {
46*3f8e9d82SAndroid Build Coastguard Worker     sk: binder::Strong<dyn ISecretkeeper>,
47*3f8e9d82SAndroid Build Coastguard Worker     encryption_key: key::AesKey,
48*3f8e9d82SAndroid Build Coastguard Worker     decryption_key: key::AesKey,
49*3f8e9d82SAndroid Build Coastguard Worker     session_id: Vec<u8>,
50*3f8e9d82SAndroid Build Coastguard Worker     // We allow seq numbers to be 0 to u64::MAX-1, increment beyond that fails
51*3f8e9d82SAndroid Build Coastguard Worker     // Sequence number for next outgoing message encryption.
52*3f8e9d82SAndroid Build Coastguard Worker     seq_num_outgoing: SeqNum,
53*3f8e9d82SAndroid Build Coastguard Worker     // Sequence number for decrypting the next incoming message.
54*3f8e9d82SAndroid Build Coastguard Worker     seq_num_incoming: SeqNum,
55*3f8e9d82SAndroid Build Coastguard Worker }
56*3f8e9d82SAndroid Build Coastguard Worker 
57*3f8e9d82SAndroid Build Coastguard Worker impl SkSession {
58*3f8e9d82SAndroid Build Coastguard Worker     /// Create a new Secretkeeper session. This triggers an AuthgraphKeyExchange protocol with a
59*3f8e9d82SAndroid Build Coastguard Worker     /// local `source` and remote `sink`.
60*3f8e9d82SAndroid Build Coastguard Worker     ///
61*3f8e9d82SAndroid Build Coastguard Worker     /// # Arguments
62*3f8e9d82SAndroid Build Coastguard Worker     /// `sk`: Secretkeeper instance
63*3f8e9d82SAndroid Build Coastguard Worker     ///
64*3f8e9d82SAndroid Build Coastguard Worker     /// `dice`: DiceArtifacts of the caller (i.e, Sk client)
65*3f8e9d82SAndroid Build Coastguard Worker     ///
66*3f8e9d82SAndroid Build Coastguard Worker     /// `expected_sk_key`: Expected Identity of Secretkeeper. If set, the claimed peer identity is
67*3f8e9d82SAndroid Build Coastguard Worker     /// matched against this and in cases of mismatch, error is returned.
new( sk: binder::Strong<dyn ISecretkeeper>, dice: &OwnedDiceArtifactsWithExplicitKey, expected_sk_key: Option<CoseKey>, ) -> Result<Self, Error>68*3f8e9d82SAndroid Build Coastguard Worker     pub fn new(
69*3f8e9d82SAndroid Build Coastguard Worker         sk: binder::Strong<dyn ISecretkeeper>,
70*3f8e9d82SAndroid Build Coastguard Worker         dice: &OwnedDiceArtifactsWithExplicitKey,
71*3f8e9d82SAndroid Build Coastguard Worker         expected_sk_key: Option<CoseKey>,
72*3f8e9d82SAndroid Build Coastguard Worker     ) -> Result<Self, Error> {
73*3f8e9d82SAndroid Build Coastguard Worker         let ag_dev = Rc::new(RefCell::new(AgDevice::new(dice, expected_sk_key)?));
74*3f8e9d82SAndroid Build Coastguard Worker         let ([encryption_key, decryption_key], session_id) =
75*3f8e9d82SAndroid Build Coastguard Worker             authgraph_key_exchange(sk.clone(), ag_dev.clone())?;
76*3f8e9d82SAndroid Build Coastguard Worker         Ok(Self {
77*3f8e9d82SAndroid Build Coastguard Worker             sk,
78*3f8e9d82SAndroid Build Coastguard Worker             encryption_key,
79*3f8e9d82SAndroid Build Coastguard Worker             decryption_key,
80*3f8e9d82SAndroid Build Coastguard Worker             session_id,
81*3f8e9d82SAndroid Build Coastguard Worker             seq_num_outgoing: SeqNum::new(),
82*3f8e9d82SAndroid Build Coastguard Worker             seq_num_incoming: SeqNum::new(),
83*3f8e9d82SAndroid Build Coastguard Worker         })
84*3f8e9d82SAndroid Build Coastguard Worker     }
85*3f8e9d82SAndroid Build Coastguard Worker 
86*3f8e9d82SAndroid Build Coastguard Worker     /// Wrapper around `ISecretkeeper::processSecretManagementRequest`. This additionally handles
87*3f8e9d82SAndroid Build Coastguard Worker     /// encryption and decryption.
secret_management_request(&mut self, req_data: &[u8]) -> Result<Vec<u8>, Error>88*3f8e9d82SAndroid Build Coastguard Worker     pub fn secret_management_request(&mut self, req_data: &[u8]) -> Result<Vec<u8>, Error> {
89*3f8e9d82SAndroid Build Coastguard Worker         let aes_gcm = boring::BoringAes;
90*3f8e9d82SAndroid Build Coastguard Worker         let rng = boring::BoringRng;
91*3f8e9d82SAndroid Build Coastguard Worker         let req_aad = self.seq_num_outgoing.get_then_increment()?;
92*3f8e9d82SAndroid Build Coastguard Worker         let request_bytes = cipher::encrypt_message(
93*3f8e9d82SAndroid Build Coastguard Worker             &aes_gcm,
94*3f8e9d82SAndroid Build Coastguard Worker             &rng,
95*3f8e9d82SAndroid Build Coastguard Worker             &self.encryption_key,
96*3f8e9d82SAndroid Build Coastguard Worker             &self.session_id,
97*3f8e9d82SAndroid Build Coastguard Worker             req_data,
98*3f8e9d82SAndroid Build Coastguard Worker             &req_aad,
99*3f8e9d82SAndroid Build Coastguard Worker         )
100*3f8e9d82SAndroid Build Coastguard Worker         .map_err(Error::CipherError)?;
101*3f8e9d82SAndroid Build Coastguard Worker 
102*3f8e9d82SAndroid Build Coastguard Worker         let response_bytes = self.sk.processSecretManagementRequest(&request_bytes)?;
103*3f8e9d82SAndroid Build Coastguard Worker 
104*3f8e9d82SAndroid Build Coastguard Worker         let response_encrypt0 = CoseEncrypt0::from_slice(&response_bytes)?;
105*3f8e9d82SAndroid Build Coastguard Worker         let expected_res_aad = self.seq_num_incoming.get_then_increment()?;
106*3f8e9d82SAndroid Build Coastguard Worker         cipher::decrypt_message(
107*3f8e9d82SAndroid Build Coastguard Worker             &aes_gcm,
108*3f8e9d82SAndroid Build Coastguard Worker             &self.decryption_key,
109*3f8e9d82SAndroid Build Coastguard Worker             &response_encrypt0,
110*3f8e9d82SAndroid Build Coastguard Worker             &expected_res_aad,
111*3f8e9d82SAndroid Build Coastguard Worker         )
112*3f8e9d82SAndroid Build Coastguard Worker         .map_err(Error::CipherError)
113*3f8e9d82SAndroid Build Coastguard Worker     }
114*3f8e9d82SAndroid Build Coastguard Worker 
115*3f8e9d82SAndroid Build Coastguard Worker     /// Get the encryption key corresponding to the session. Note on usage: This (along with other
116*3f8e9d82SAndroid Build Coastguard Worker     /// getters [`decryption_key()`] & [`session_id()`]) can be used for custom encrypting requests
117*3f8e9d82SAndroid Build Coastguard Worker     /// (for ex, with different aad, instead of using [`secret_management_request`] method.
118*3f8e9d82SAndroid Build Coastguard Worker     /// In that case, seq_num_outgoing & seq_num_incoming will be out of sync. Recommended use for
119*3f8e9d82SAndroid Build Coastguard Worker     /// testing only.
encryption_key(&self) -> &key::AesKey120*3f8e9d82SAndroid Build Coastguard Worker     pub fn encryption_key(&self) -> &key::AesKey {
121*3f8e9d82SAndroid Build Coastguard Worker         &self.encryption_key
122*3f8e9d82SAndroid Build Coastguard Worker     }
123*3f8e9d82SAndroid Build Coastguard Worker 
124*3f8e9d82SAndroid Build Coastguard Worker     /// Get the decryption key corresponding to the session.
decryption_key(&self) -> &key::AesKey125*3f8e9d82SAndroid Build Coastguard Worker     pub fn decryption_key(&self) -> &key::AesKey {
126*3f8e9d82SAndroid Build Coastguard Worker         &self.decryption_key
127*3f8e9d82SAndroid Build Coastguard Worker     }
128*3f8e9d82SAndroid Build Coastguard Worker 
129*3f8e9d82SAndroid Build Coastguard Worker     /// Get the session_id.
session_id(&self) -> &[u8]130*3f8e9d82SAndroid Build Coastguard Worker     pub fn session_id(&self) -> &[u8] {
131*3f8e9d82SAndroid Build Coastguard Worker         &self.session_id
132*3f8e9d82SAndroid Build Coastguard Worker     }
133*3f8e9d82SAndroid Build Coastguard Worker }
134*3f8e9d82SAndroid Build Coastguard Worker 
135*3f8e9d82SAndroid Build Coastguard Worker impl fmt::Debug for SkSession {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result136*3f8e9d82SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
137*3f8e9d82SAndroid Build Coastguard Worker         f.debug_struct("SkSession").field("session_id", &hex::encode(&self.session_id)).finish()
138*3f8e9d82SAndroid Build Coastguard Worker     }
139*3f8e9d82SAndroid Build Coastguard Worker }
140*3f8e9d82SAndroid Build Coastguard Worker 
141*3f8e9d82SAndroid Build Coastguard Worker /// Errors thrown by this SkSession.
142*3f8e9d82SAndroid Build Coastguard Worker #[derive(Debug)]
143*3f8e9d82SAndroid Build Coastguard Worker pub enum Error {
144*3f8e9d82SAndroid Build Coastguard Worker     /// These are server errors : thrown from remote instance (of Authgraph or Secretkeeper)
145*3f8e9d82SAndroid Build Coastguard Worker     BinderStatus(binder::Status),
146*3f8e9d82SAndroid Build Coastguard Worker     /// These are errors thrown from (local) source Authgraph instance.
147*3f8e9d82SAndroid Build Coastguard Worker     AuthgraphError(authgraph_core::error::Error),
148*3f8e9d82SAndroid Build Coastguard Worker     /// Error originating while encryption/decryption of packets (at source).
149*3f8e9d82SAndroid Build Coastguard Worker     CipherError(ApiError),
150*3f8e9d82SAndroid Build Coastguard Worker     /// Errors originating in the coset library.
151*3f8e9d82SAndroid Build Coastguard Worker     CoseError(coset::CoseError),
152*3f8e9d82SAndroid Build Coastguard Worker     /// Unexpected item encountered (got, want).
153*3f8e9d82SAndroid Build Coastguard Worker     UnexpectedItem(&'static str, &'static str),
154*3f8e9d82SAndroid Build Coastguard Worker     /// The set of errors from secretkeeper_comm library.
155*3f8e9d82SAndroid Build Coastguard Worker     SkCommError(secretkeeper_comm::data_types::error::Error),
156*3f8e9d82SAndroid Build Coastguard Worker }
157*3f8e9d82SAndroid Build Coastguard Worker 
158*3f8e9d82SAndroid Build Coastguard Worker impl std::error::Error for Error {}
159*3f8e9d82SAndroid Build Coastguard Worker 
160*3f8e9d82SAndroid Build Coastguard Worker impl std::fmt::Display for Error {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result161*3f8e9d82SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
162*3f8e9d82SAndroid Build Coastguard Worker         match self {
163*3f8e9d82SAndroid Build Coastguard Worker             Self::BinderStatus(e) => write!(f, "Binder error {e:?}"),
164*3f8e9d82SAndroid Build Coastguard Worker             Self::AuthgraphError(e) => write!(f, "Local Authgraph instance error {e:?}"),
165*3f8e9d82SAndroid Build Coastguard Worker             Self::CipherError(e) => write!(f, "Error in encryption/decryption of packets {e:?}"),
166*3f8e9d82SAndroid Build Coastguard Worker             Self::CoseError(e) => write!(f, "Errors originating in the coset library {e:?}"),
167*3f8e9d82SAndroid Build Coastguard Worker             Self::UnexpectedItem(got, want) => {
168*3f8e9d82SAndroid Build Coastguard Worker                 write!(f, "Unexpected item - Got:{got}, Expected:{want}")
169*3f8e9d82SAndroid Build Coastguard Worker             }
170*3f8e9d82SAndroid Build Coastguard Worker             Self::SkCommError(e) => write!(f, "secretkeeper_comm error: {e:?}"),
171*3f8e9d82SAndroid Build Coastguard Worker         }
172*3f8e9d82SAndroid Build Coastguard Worker     }
173*3f8e9d82SAndroid Build Coastguard Worker }
174*3f8e9d82SAndroid Build Coastguard Worker 
175*3f8e9d82SAndroid Build Coastguard Worker impl From<authgraph_core::error::Error> for Error {
from(e: authgraph_core::error::Error) -> Self176*3f8e9d82SAndroid Build Coastguard Worker     fn from(e: authgraph_core::error::Error) -> Self {
177*3f8e9d82SAndroid Build Coastguard Worker         Self::AuthgraphError(e)
178*3f8e9d82SAndroid Build Coastguard Worker     }
179*3f8e9d82SAndroid Build Coastguard Worker }
180*3f8e9d82SAndroid Build Coastguard Worker 
181*3f8e9d82SAndroid Build Coastguard Worker impl From<binder::Status> for Error {
from(s: binder::Status) -> Self182*3f8e9d82SAndroid Build Coastguard Worker     fn from(s: binder::Status) -> Self {
183*3f8e9d82SAndroid Build Coastguard Worker         Self::BinderStatus(s)
184*3f8e9d82SAndroid Build Coastguard Worker     }
185*3f8e9d82SAndroid Build Coastguard Worker }
186*3f8e9d82SAndroid Build Coastguard Worker 
187*3f8e9d82SAndroid Build Coastguard Worker impl From<coset::CoseError> for Error {
from(e: coset::CoseError) -> Self188*3f8e9d82SAndroid Build Coastguard Worker     fn from(e: coset::CoseError) -> Self {
189*3f8e9d82SAndroid Build Coastguard Worker         Self::CoseError(e)
190*3f8e9d82SAndroid Build Coastguard Worker     }
191*3f8e9d82SAndroid Build Coastguard Worker }
192*3f8e9d82SAndroid Build Coastguard Worker 
193*3f8e9d82SAndroid Build Coastguard Worker impl From<secretkeeper_comm::data_types::error::Error> for Error {
from(e: secretkeeper_comm::data_types::error::Error) -> Self194*3f8e9d82SAndroid Build Coastguard Worker     fn from(e: secretkeeper_comm::data_types::error::Error) -> Self {
195*3f8e9d82SAndroid Build Coastguard Worker         Self::SkCommError(e)
196*3f8e9d82SAndroid Build Coastguard Worker     }
197*3f8e9d82SAndroid Build Coastguard Worker }
198*3f8e9d82SAndroid Build Coastguard Worker 
199*3f8e9d82SAndroid Build Coastguard Worker /// Perform AuthGraph key exchange, returning the session keys and session ID.
authgraph_key_exchange( sk: binder::Strong<dyn ISecretkeeper>, ag_dev: Rc<RefCell<AgDevice>>, ) -> Result<([key::AesKey; 2], Vec<u8>), Error>200*3f8e9d82SAndroid Build Coastguard Worker fn authgraph_key_exchange(
201*3f8e9d82SAndroid Build Coastguard Worker     sk: binder::Strong<dyn ISecretkeeper>,
202*3f8e9d82SAndroid Build Coastguard Worker     ag_dev: Rc<RefCell<AgDevice>>,
203*3f8e9d82SAndroid Build Coastguard Worker ) -> Result<([key::AesKey; 2], Vec<u8>), Error> {
204*3f8e9d82SAndroid Build Coastguard Worker     let sink = sk.getAuthGraphKe()?;
205*3f8e9d82SAndroid Build Coastguard Worker     let mut source = ke::AuthGraphParticipant::new(
206*3f8e9d82SAndroid Build Coastguard Worker         boring::crypto_trait_impls(),
207*3f8e9d82SAndroid Build Coastguard Worker         ag_dev,
208*3f8e9d82SAndroid Build Coastguard Worker         1, // Each SkSession supports only 1 open Authgraph session.
209*3f8e9d82SAndroid Build Coastguard Worker     )?;
210*3f8e9d82SAndroid Build Coastguard Worker     key_exchange(&mut source, sink)
211*3f8e9d82SAndroid Build Coastguard Worker }
212*3f8e9d82SAndroid Build Coastguard Worker 
213*3f8e9d82SAndroid Build Coastguard Worker /// Perform AuthGraph key exchange with the provided sink and local source implementation.
214*3f8e9d82SAndroid Build Coastguard Worker /// Return the agreed AES keys in plaintext, together with the session ID.
key_exchange( local_source: &mut ke::AuthGraphParticipant, sink: binder::Strong<dyn IAuthGraphKeyExchange>, ) -> Result<([key::AesKey; 2], Vec<u8>), Error>215*3f8e9d82SAndroid Build Coastguard Worker fn key_exchange(
216*3f8e9d82SAndroid Build Coastguard Worker     local_source: &mut ke::AuthGraphParticipant,
217*3f8e9d82SAndroid Build Coastguard Worker     sink: binder::Strong<dyn IAuthGraphKeyExchange>,
218*3f8e9d82SAndroid Build Coastguard Worker ) -> Result<([key::AesKey; 2], Vec<u8>), Error> {
219*3f8e9d82SAndroid Build Coastguard Worker     // Step 1: create an ephemeral ECDH key at the (local) source.
220*3f8e9d82SAndroid Build Coastguard Worker     let source_init_info = local_source.create()?;
221*3f8e9d82SAndroid Build Coastguard Worker 
222*3f8e9d82SAndroid Build Coastguard Worker     // Step 2: pass the source's ECDH public key and other session info to the (remote) sink.
223*3f8e9d82SAndroid Build Coastguard Worker     let init_result = sink.init(
224*3f8e9d82SAndroid Build Coastguard Worker         &build_plain_pub_key(&source_init_info.ke_key.pub_key)?,
225*3f8e9d82SAndroid Build Coastguard Worker         &vec_to_identity(&source_init_info.identity),
226*3f8e9d82SAndroid Build Coastguard Worker         &source_init_info.nonce,
227*3f8e9d82SAndroid Build Coastguard Worker         source_init_info.version,
228*3f8e9d82SAndroid Build Coastguard Worker     )?;
229*3f8e9d82SAndroid Build Coastguard Worker     let sink_init_info = init_result.sessionInitiationInfo;
230*3f8e9d82SAndroid Build Coastguard Worker     let sink_pub_key = extract_plain_pub_key(&sink_init_info.key.pubKey)?;
231*3f8e9d82SAndroid Build Coastguard Worker     let sink_info = init_result.sessionInfo;
232*3f8e9d82SAndroid Build Coastguard Worker 
233*3f8e9d82SAndroid Build Coastguard Worker     // Step 3: pass the sink's ECDH public key and other session info to the (local) source, so it
234*3f8e9d82SAndroid Build Coastguard Worker     // can calculate the same pair of symmetric keys.
235*3f8e9d82SAndroid Build Coastguard Worker     let source_info = local_source.finish(
236*3f8e9d82SAndroid Build Coastguard Worker         &sink_pub_key.plainPubKey,
237*3f8e9d82SAndroid Build Coastguard Worker         &sink_init_info.identity.identity,
238*3f8e9d82SAndroid Build Coastguard Worker         &sink_info.signature.signature,
239*3f8e9d82SAndroid Build Coastguard Worker         &sink_init_info.nonce,
240*3f8e9d82SAndroid Build Coastguard Worker         sink_init_info.version,
241*3f8e9d82SAndroid Build Coastguard Worker         source_init_info.ke_key,
242*3f8e9d82SAndroid Build Coastguard Worker     )?;
243*3f8e9d82SAndroid Build Coastguard Worker 
244*3f8e9d82SAndroid Build Coastguard Worker     // Step 4: pass the (local) source's session ID signature back to the sink, so it can check it
245*3f8e9d82SAndroid Build Coastguard Worker     // and update the symmetric keys so they're marked as authentication complete.
246*3f8e9d82SAndroid Build Coastguard Worker     let _sink_arcs = sink.authenticationComplete(
247*3f8e9d82SAndroid Build Coastguard Worker         &vec_to_signature(&source_info.session_id_signature),
248*3f8e9d82SAndroid Build Coastguard Worker         &sink_info.sharedKeys,
249*3f8e9d82SAndroid Build Coastguard Worker     )?;
250*3f8e9d82SAndroid Build Coastguard Worker 
251*3f8e9d82SAndroid Build Coastguard Worker     // Decrypt and return the session keys.
252*3f8e9d82SAndroid Build Coastguard Worker     let decrypted_shared_keys_array = local_source
253*3f8e9d82SAndroid Build Coastguard Worker         .decipher_shared_keys_from_arcs(&source_info.shared_keys)?
254*3f8e9d82SAndroid Build Coastguard Worker         .try_into()
255*3f8e9d82SAndroid Build Coastguard Worker         .map_err(|_| Error::UnexpectedItem("Array", "Array of size 2"))?;
256*3f8e9d82SAndroid Build Coastguard Worker 
257*3f8e9d82SAndroid Build Coastguard Worker     Ok((decrypted_shared_keys_array, source_info.session_id))
258*3f8e9d82SAndroid Build Coastguard Worker }
259*3f8e9d82SAndroid Build Coastguard Worker 
build_plain_pub_key(pub_key: &Option<Vec<u8>>) -> Result<PubKey, Error>260*3f8e9d82SAndroid Build Coastguard Worker fn build_plain_pub_key(pub_key: &Option<Vec<u8>>) -> Result<PubKey, Error> {
261*3f8e9d82SAndroid Build Coastguard Worker     Ok(PubKey::PlainKey(PlainPubKey {
262*3f8e9d82SAndroid Build Coastguard Worker         plainPubKey: pub_key.clone().ok_or(Error::UnexpectedItem("None", "Some bytes"))?,
263*3f8e9d82SAndroid Build Coastguard Worker     }))
264*3f8e9d82SAndroid Build Coastguard Worker }
265*3f8e9d82SAndroid Build Coastguard Worker 
extract_plain_pub_key(pub_key: &Option<PubKey>) -> Result<&PlainPubKey, Error>266*3f8e9d82SAndroid Build Coastguard Worker fn extract_plain_pub_key(pub_key: &Option<PubKey>) -> Result<&PlainPubKey, Error> {
267*3f8e9d82SAndroid Build Coastguard Worker     match pub_key {
268*3f8e9d82SAndroid Build Coastguard Worker         Some(PubKey::PlainKey(pub_key)) => Ok(pub_key),
269*3f8e9d82SAndroid Build Coastguard Worker         Some(PubKey::SignedKey(_)) => Err(Error::UnexpectedItem("Signed Key", "Public Key")),
270*3f8e9d82SAndroid Build Coastguard Worker         None => Err(Error::UnexpectedItem("No key", "Public key")),
271*3f8e9d82SAndroid Build Coastguard Worker     }
272*3f8e9d82SAndroid Build Coastguard Worker }
273*3f8e9d82SAndroid Build Coastguard Worker 
vec_to_identity(data: &[u8]) -> Identity274*3f8e9d82SAndroid Build Coastguard Worker fn vec_to_identity(data: &[u8]) -> Identity {
275*3f8e9d82SAndroid Build Coastguard Worker     Identity { identity: data.to_vec() }
276*3f8e9d82SAndroid Build Coastguard Worker }
277*3f8e9d82SAndroid Build Coastguard Worker 
vec_to_signature(data: &[u8]) -> SessionIdSignature278*3f8e9d82SAndroid Build Coastguard Worker fn vec_to_signature(data: &[u8]) -> SessionIdSignature {
279*3f8e9d82SAndroid Build Coastguard Worker     SessionIdSignature { signature: data.to_vec() }
280*3f8e9d82SAndroid Build Coastguard Worker }
281*3f8e9d82SAndroid Build Coastguard Worker 
282*3f8e9d82SAndroid Build Coastguard Worker #[cfg(test)]
283*3f8e9d82SAndroid Build Coastguard Worker rdroidtest::test_main!();
284