diff --git a/services/identity/src/service.rs b/services/identity/src/service.rs --- a/services/identity/src/service.rs +++ b/services/identity/src/service.rs @@ -1,12 +1,12 @@ use chrono::Utc; use constant_time_eq::constant_time_eq; use futures_core::Stream; -use opaque_ke::ServerRegistration; use opaque_ke::{ CredentialFinalization, CredentialRequest, RegistrationRequest as PakeRegistrationRequest, ServerLogin, ServerLoginStartParameters, }; +use opaque_ke::{RegistrationUpload, ServerRegistration}; use rand::rngs::OsRng; use rand::{CryptoRng, Rng}; use rusoto_core::RusotoError; @@ -576,3 +576,52 @@ } } } + +async fn pake_registration_finish( + user_id: &str, + client: DatabaseClient, + registration_upload_bytes: &[u8], + server_registration: Option>, + num_messages_received: u8, +) -> Result<(), Status> { + if num_messages_received != 1 { + error!("Too many messages received in stream, aborting"); + return Err(Status::aborted("please retry")); + } + if user_id.is_empty() { + error!("Incomplete data: user ID not provided"); + return Err(Status::aborted("user not found")); + } + let server_registration_finish_result = server_registration + .ok_or_else(|| Status::aborted("registration failed"))? + .finish( + RegistrationUpload::deserialize(registration_upload_bytes).map_err( + |e| { + error!("Failed to deserialize registration upload bytes: {}", e); + Status::aborted("registration failed") + }, + )?, + ) + .map_err(|e| { + error!( + "Encountered a PAKE protocol error when finishing registration: {}", + e + ); + Status::aborted("server error") + })?; + + match client + .put_pake_registration( + user_id.to_string(), + server_registration_finish_result, + ) + .await + { + Ok(_) => Ok(()), + Err(RusotoError::Service(PutItemError::ResourceNotFound(_))) + | Err(RusotoError::Credentials(_)) => { + Err(Status::failed_precondition("internal error")) + } + Err(_) => Err(Status::unavailable("please retry")), + } +}