webrtc_dtls/handshake/
handshake_message_server_key_exchange.rs

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