rtc_dtls/handshake/
handshake_message_server_key_exchange.rs

1#[cfg(test)]
2mod handshake_message_server_key_exchange_test;
3
4use super::*;
5use crate::curve::named_curve::*;
6use crate::curve::*;
7use crate::signature_hash_algorithm::*;
8
9use byteorder::{BigEndian, WriteBytesExt};
10use std::io::{Read, Write};
11
12// Structure supports ECDH and PSK
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct HandshakeMessageServerKeyExchange {
15    pub(crate) identity_hint: Vec<u8>,
16
17    pub(crate) elliptic_curve_type: EllipticCurveType,
18    pub(crate) named_curve: NamedCurve,
19    pub(crate) public_key: Vec<u8>,
20    pub(crate) algorithm: SignatureHashAlgorithm,
21    pub(crate) signature: Vec<u8>,
22}
23
24impl HandshakeMessageServerKeyExchange {
25    pub fn handshake_type(&self) -> HandshakeType {
26        HandshakeType::ServerKeyExchange
27    }
28
29    pub fn size(&self) -> usize {
30        if !self.identity_hint.is_empty() {
31            2 + self.identity_hint.len()
32        } else {
33            1 + 2 + 1 + self.public_key.len() + 2 + 2 + self.signature.len()
34        }
35    }
36
37    pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<()> {
38        if !self.identity_hint.is_empty() {
39            writer.write_u16::<BigEndian>(self.identity_hint.len() as u16)?;
40            writer.write_all(&self.identity_hint)?;
41            return Ok(writer.flush()?);
42        }
43
44        writer.write_u8(self.elliptic_curve_type as u8)?;
45        writer.write_u16::<BigEndian>(self.named_curve as u16)?;
46
47        writer.write_u8(self.public_key.len() as u8)?;
48        writer.write_all(&self.public_key)?;
49
50        writer.write_u8(self.algorithm.hash as u8)?;
51        writer.write_u8(self.algorithm.signature as u8)?;
52
53        writer.write_u16::<BigEndian>(self.signature.len() as u16)?;
54        writer.write_all(&self.signature)?;
55
56        Ok(writer.flush()?)
57    }
58
59    pub fn unmarshal<R: Read>(reader: &mut R) -> Result<Self> {
60        let mut data = vec![];
61        reader.read_to_end(&mut data)?;
62
63        // If parsed as PSK return early and only populate PSK Identity Hint
64        let psk_length = ((data[0] as u16) << 8) | data[1] as u16;
65        if data.len() == psk_length as usize + 2 {
66            return Ok(HandshakeMessageServerKeyExchange {
67                identity_hint: data[2..].to_vec(),
68
69                elliptic_curve_type: EllipticCurveType::Unsupported,
70                named_curve: NamedCurve::Unsupported,
71                public_key: vec![],
72                algorithm: SignatureHashAlgorithm {
73                    hash: HashAlgorithm::Unsupported,
74                    signature: SignatureAlgorithm::Unsupported,
75                },
76                signature: vec![],
77            });
78        }
79
80        let elliptic_curve_type = data[0].into();
81        if data[1..].len() < 2 {
82            return Err(Error::ErrBufferTooSmall);
83        }
84
85        let named_curve = (((data[1] as u16) << 8) | data[2] as u16).into();
86        if data.len() < 4 {
87            return Err(Error::ErrBufferTooSmall);
88        }
89
90        let public_key_length = data[3] as usize;
91        let mut offset = 4 + public_key_length;
92        if data.len() < offset {
93            return Err(Error::ErrBufferTooSmall);
94        }
95        let public_key = data[4..offset].to_vec();
96        if data.len() <= offset {
97            return Err(Error::ErrBufferTooSmall);
98        }
99
100        let hash_algorithm = data[offset].into();
101        offset += 1;
102        if data.len() <= offset {
103            return Err(Error::ErrBufferTooSmall);
104        }
105
106        let signature_algorithm = data[offset].into();
107        offset += 1;
108        if data.len() < offset + 2 {
109            return Err(Error::ErrBufferTooSmall);
110        }
111
112        let signature_length = (((data[offset] as u16) << 8) | data[offset + 1] as u16) as usize;
113        offset += 2;
114        if data.len() < offset + signature_length {
115            return Err(Error::ErrBufferTooSmall);
116        }
117        let signature = data[offset..offset + signature_length].to_vec();
118
119        Ok(HandshakeMessageServerKeyExchange {
120            identity_hint: vec![],
121
122            elliptic_curve_type,
123            named_curve,
124            public_key,
125            algorithm: SignatureHashAlgorithm {
126                hash: hash_algorithm,
127                signature: signature_algorithm,
128            },
129            signature,
130        })
131    }
132}