AuthClientFinalize State: - state, a ClientAkeState structure. Input: - cleartext_credentials, a CleartextCredentials structure. - client_private_key, the client's private key. - ke2, a KE2 message structure. Output: - ke3, a KE3 structure. - session_key, the shared session secret. Exceptions: - ServerAuthenticationError, the handshake fails. def AuthClientFinalize(cleartext_credentials, client_private_key, ke2): dh1 = DiffieHellman(state.client_secret, ke2.auth_response.server_public_keyshare) dh2 = DiffieHellman(state.client_secret, cleartext_credentials.server_public_key) dh3 = DiffieHellman(client_private_key, ke2.auth_response.server_public_keyshare) ikm = concat(dh1, dh2, dh3) preamble = Preamble(cleartext_credentials.client_identity, state.ke1, cleartext_credentials.server_identity, ke2.credential_response, ke2.auth_response.server_nonce, ke2.auth_response.server_public_keyshare) Km2, Km3, session_key = DeriveKeys(ikm, preamble) expected_server_mac = MAC(Km2, Hash(preamble)) if !ct_equal(ke2.auth_response.server_mac, expected_server_mac), raise ServerAuthenticationError client_mac = MAC(Km3, Hash(concat(preamble, expected_server_mac))) ke3 = KE3 { client_mac } return (ke3, session_key)