aboutsummaryrefslogtreecommitdiffhomepage
path: root/oxish-proto/src/key_exchange.rs
diff options
context:
space:
mode:
Diffstat (limited to 'oxish-proto/src/key_exchange.rs')
-rw-r--r--oxish-proto/src/key_exchange.rs103
1 files changed, 2 insertions, 101 deletions
diff --git a/oxish-proto/src/key_exchange.rs b/oxish-proto/src/key_exchange.rs
index eaa75e4..17b056e 100644
--- a/oxish-proto/src/key_exchange.rs
+++ b/oxish-proto/src/key_exchange.rs
@@ -2,7 +2,6 @@ use core::fmt;
use std::borrow::Cow;
use tracing::debug;
-use zeroize::Zeroizing;
use crate::{
Decode, Decoded, Encode, IncomingPacket, MessageType, Pretty, ProtoError, PublicKeyAlgorithm,
@@ -10,6 +9,7 @@ use crate::{
CryptoError, CryptoProvider, Digest, HandshakeBuffer, HandshakeHash, KeyDerivation,
KeySourceSide, SharedSecret, SigningKey,
},
+ host_keys::{HostKeys, ServerHostKey, SessionHostKey},
named::{
CompressionAlgorithm, EncryptionAlgorithm, ExtensionId, ExtensionName, IncomingNameList,
KeyExchangeAlgorithm, KeyExchangeAlgorithmOrExtensionId, Language, MacAlgorithm,
@@ -485,105 +485,6 @@ impl Encode for EcdhKeyExchangeReply {
}
}
-/// The server's host keys, used to authenticate the key exchange
-#[expect(clippy::type_complexity)]
-pub struct HostKeys(Vec<(Zeroizing<Vec<u8>>, Box<dyn SigningKey>)>);
-
-impl HostKeys {
- /// Create a new set of host keys from the given PKCS#8 private keys
- ///
- /// `pkcs8` must have more than 0 and less than 16 elements.
- pub fn new(
- pkcs8: impl Iterator<Item = Zeroizing<Vec<u8>>>,
- provider: &dyn CryptoProvider,
- ) -> Result<Self, ProtoError> {
- let mut keys = Vec::new();
- for pkcs8 in pkcs8 {
- if keys.len() >= Self::MAX_KEYS {
- return Err(ProtoError::TooManyHostKeys);
- }
-
- let signing_key = provider.signing_key_from_pkcs8(&pkcs8)?;
- keys.push((pkcs8, signing_key));
- }
-
- if keys.is_empty() {
- return Err(ProtoError::NoHostKeys);
- }
-
- Ok(Self(keys))
- }
-
- /// Select the host key matching the negotiated algorithm
- pub fn key<'a>(&'a self, negotiated: &Negotiated) -> Result<ServerHostKey<'a>, CryptoError> {
- let mut iter = self.0.iter();
- match iter.find(|(_, key)| key.algorithm() == negotiated.server_host_key) {
- Some((pkcs8, key)) => Ok(ServerHostKey {
- pkcs8,
- key: key.as_ref(),
- }),
- None => Err(CryptoError::UnknownAlgorithm),
- }
- }
-
- /// The public key algorithms of the held host keys
- pub fn algorithms(&self) -> impl Iterator<Item = PublicKeyAlgorithm<'static>> + '_ {
- self.0.iter().map(|(_, key)| key.algorithm())
- }
-
- const MAX_KEYS: usize = 16;
-}
-
-/// A borrowed single host key, used to sign the key exchange output
-pub struct ServerHostKey<'a> {
- pkcs8: &'a Zeroizing<Vec<u8>>,
- key: &'a dyn SigningKey,
-}
-
-impl Encode for ServerHostKey<'_> {
- fn encode(&self, buf: &mut Vec<u8>) {
- let Self { pkcs8, key: _ } = self;
- pkcs8.encode(buf);
- }
-}
-
-#[doc(hidden)] // for testing
-impl<'a> From<(&'a Zeroizing<Vec<u8>>, &'a dyn SigningKey)> for ServerHostKey<'a> {
- fn from((pkcs8, key): (&'a Zeroizing<Vec<u8>>, &'a dyn SigningKey)) -> Self {
- Self { pkcs8, key }
- }
-}
-
-/// A single host key, used to sign rekeying exchanges
-pub struct SessionHostKey(Box<dyn SigningKey>);
-
-impl SessionHostKey {
- /// Create a new session host key from a borrowed server host key
- pub fn from_server(
- host_key: ServerHostKey<'_>,
- provider: &dyn CryptoProvider,
- ) -> Result<Self, ProtoError> {
- Ok(Self(provider.signing_key_from_pkcs8(host_key.pkcs8)?))
- }
-
- /// Decode a host key from encoded PKCS#8 bytes
- pub fn decode<'a>(
- buf: &'a [u8],
- provider: &dyn CryptoProvider,
- ) -> Result<Decoded<'a, Self>, ProtoError> {
- let Decoded { value: pkcs8, next } = <&[u8]>::decode(buf)?;
- Ok(Decoded {
- value: Self(provider.signing_key_from_pkcs8(pkcs8)?),
- next,
- })
- }
-
- /// The public key algorithm of this host key
- pub fn algorithm(&self) -> PublicKeyAlgorithm<'static> {
- self.0.algorithm()
- }
-}
-
struct KeyExchangeStarted {
shared_secret: SharedSecret,
exchange_hash: Digest,
@@ -753,7 +654,7 @@ impl fmt::Debug for TaggedSignature<'_> {
pub struct Negotiated {
/// Negotiated key exchange algorithm
pub key_exchange: KeyExchangeAlgorithm<'static>,
- server_host_key: PublicKeyAlgorithm<'static>,
+ pub(crate) server_host_key: PublicKeyAlgorithm<'static>,
encryption_client_to_server: EncryptionAlgorithm<'static>,
encryption_server_to_client: EncryptionAlgorithm<'static>,
/// Whether the client requested `SSH_MSG_EXT_INFO` via `ext-info-c` (RFC 8308)