fn on_secret()

in quic/s2n-quic-tls/src/callback.rs [152:285]


    fn on_secret(
        &mut self,
        conn: *mut s2n_connection,
        id: s2n_secret_type_t::Type,
        secret: &mut [u8],
    ) -> Result<(), transport::Error> {
        match core::mem::replace(&mut self.state.secrets, Secrets::Waiting) {
            Secrets::Waiting => {
                if id == s2n_secret_type_t::CLIENT_EARLY_TRAFFIC_SECRET {
                    return Ok(());
                }

                let (prk_algo, _aead, cipher_suite) =
                    get_algo_type(conn).ok_or(tls::Error::INTERNAL_ERROR)?;
                let secret = Prk::new_less_safe(prk_algo, secret);
                self.state.secrets = Secrets::Half { secret, id };
                self.state.cipher_suite = cipher_suite;

                Ok(())
            }
            Secrets::Half {
                id: other_id,
                secret: other_secret,
            } => {
                let (prk_algo, aead_algo, cipher_suite) =
                    get_algo_type(conn).ok_or(tls::Error::INTERNAL_ERROR)?;
                let secret = Prk::new_less_safe(prk_algo, secret);
                self.state.cipher_suite = cipher_suite;
                let pair = match (id, other_id) {
                    (
                        s2n_secret_type_t::CLIENT_HANDSHAKE_TRAFFIC_SECRET,
                        s2n_secret_type_t::SERVER_HANDSHAKE_TRAFFIC_SECRET,
                    )
                    | (
                        s2n_secret_type_t::CLIENT_APPLICATION_TRAFFIC_SECRET,
                        s2n_secret_type_t::SERVER_APPLICATION_TRAFFIC_SECRET,
                    ) => SecretPair {
                        client: secret,
                        server: other_secret,
                    },
                    (
                        s2n_secret_type_t::SERVER_HANDSHAKE_TRAFFIC_SECRET,
                        s2n_secret_type_t::CLIENT_HANDSHAKE_TRAFFIC_SECRET,
                    )
                    | (
                        s2n_secret_type_t::SERVER_APPLICATION_TRAFFIC_SECRET,
                        s2n_secret_type_t::CLIENT_APPLICATION_TRAFFIC_SECRET,
                    ) => SecretPair {
                        server: secret,
                        client: other_secret,
                    },
                    _ => {
                        debug_assert!(false, "invalid key phase");
                        return Err(transport::Error::INTERNAL_ERROR);
                    }
                };

                // Flush the send buffer before transitioning to the next phase
                self.flush();

                match self.state.tx_phase {
                    HandshakePhase::Initial => {
                        let (key, header_key) = HandshakeKey::new(self.endpoint, aead_algo, pair)
                            .expect("invalid cipher");

                        if !self.server_params.is_empty() {
                            debug_assert!(self.endpoint.is_server());

                            // Since the client transport parameters are sent in the Initial packet space
                            // we can access them early on in the handshake, allowing the server transport
                            // parameters to be configured based on the client's parameters.
                            unsafe {
                                // Safety: conn needs to outlive params
                                let client_params = get_application_params(conn)?;

                                // Allow for additional server params to be appended that depend
                                // on the given client params
                                self.context.on_client_application_params(
                                    client_params,
                                    self.server_params,
                                )?;

                                // Now set the server transport parameters on the connection for
                                // transmission to the client
                                s2n_connection_set_quic_transport_parameters(
                                    conn,
                                    self.server_params.as_ptr(),
                                    self.server_params.len() as _,
                                );
                            }
                            // We've given the transport parameters to s2n-tls, so clear
                            // `server_params` to ensure they are not set again.
                            self.server_params.clear();
                        }

                        self.context.on_handshake_keys(key, header_key)?;
                        self.state.tx_phase.transition();
                        self.state.rx_phase.transition();
                    }
                    _ => {
                        let (key, header_key) =
                            OneRttKey::new(self.endpoint, aead_algo, pair).expect("invalid cipher");
                        // At this point the server is done writing Handshake messages
                        if self.endpoint.is_server() {
                            self.state.tx_phase.transition();
                        }
                        let params = unsafe {
                            // Safety: conn needs to outlive params
                            let application_protocol =
                                Bytes::copy_from_slice(get_application_protocol(conn)?);
                            self.context.on_application_protocol(application_protocol)?;

                            // Client has already emitted the server name elsewhere
                            if self.endpoint.is_server() {
                                if let Some(server_name) = get_server_name(conn) {
                                    self.context.on_server_name(server_name)?;
                                }
                            }

                            if let Some(named_group) = get_key_exchange_group(conn) {
                                self.context.on_key_exchange_group(named_group)?;
                            }

                            get_application_params(conn)?
                        };

                        self.context.on_one_rtt_keys(key, header_key, params)?;
                    }
                }

                Ok(())
            }
        }
    }