rtc_dtls/signature_hash_algorithm/
mod.rs1#[cfg(test)]
2mod signature_hash_algorithm_test;
3
4use std::fmt;
5
6use crate::crypto::*;
7use shared::error::*;
8
9#[derive(Copy, Clone, Debug, PartialEq, Eq)]
13pub enum HashAlgorithm {
15 Md2 = 0, Md5 = 1, Sha1 = 2, Sha224 = 3,
23 Sha256 = 4,
25 Sha384 = 5,
27 Sha512 = 6,
29 Ed25519 = 8,
31 Unsupported,
33}
34
35impl From<u8> for HashAlgorithm {
36 fn from(val: u8) -> Self {
37 match val {
38 0 => HashAlgorithm::Md2,
39 1 => HashAlgorithm::Md5,
40 2 => HashAlgorithm::Sha1,
41 3 => HashAlgorithm::Sha224,
42 4 => HashAlgorithm::Sha256,
43 5 => HashAlgorithm::Sha384,
44 6 => HashAlgorithm::Sha512,
45 8 => HashAlgorithm::Ed25519,
46 _ => HashAlgorithm::Unsupported,
47 }
48 }
49}
50
51impl fmt::Display for HashAlgorithm {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 match *self {
54 HashAlgorithm::Md2 => write!(f, "md2"),
55 HashAlgorithm::Md5 => write!(f, "md5"), HashAlgorithm::Sha1 => write!(f, "sha-1"), HashAlgorithm::Sha224 => write!(f, "sha-224"), HashAlgorithm::Sha256 => write!(f, "sha-256"), HashAlgorithm::Sha384 => write!(f, "sha-384"), HashAlgorithm::Sha512 => write!(f, "sha-512"), HashAlgorithm::Ed25519 => write!(f, "null"), _ => write!(f, "unknown or unsupported hash algorithm"),
63 }
64 }
65}
66
67impl HashAlgorithm {
68 pub(crate) fn insecure(&self) -> bool {
69 matches!(
70 *self,
71 HashAlgorithm::Md2 | HashAlgorithm::Md5 | HashAlgorithm::Sha1
72 )
73 }
74
75 pub(crate) fn invalid(&self) -> bool {
76 matches!(*self, HashAlgorithm::Md2)
77 }
78}
79
80#[derive(Copy, Clone, Debug, PartialEq, Eq)]
82pub enum SignatureAlgorithm {
84 Rsa = 1,
86 Ecdsa = 3,
88 Ed25519 = 7,
90 Unsupported,
92}
93
94impl From<u8> for SignatureAlgorithm {
95 fn from(val: u8) -> Self {
96 match val {
97 1 => SignatureAlgorithm::Rsa,
98 3 => SignatureAlgorithm::Ecdsa,
99 7 => SignatureAlgorithm::Ed25519,
100 _ => SignatureAlgorithm::Unsupported,
101 }
102 }
103}
104
105#[derive(Copy, Clone, Debug, PartialEq, Eq)]
106pub struct SignatureHashAlgorithm {
108 pub hash: HashAlgorithm,
110 pub signature: SignatureAlgorithm,
112}
113
114impl SignatureHashAlgorithm {
115 pub(crate) fn is_compatible(&self, private_key: &CryptoPrivateKey) -> bool {
117 match &private_key.kind {
118 CryptoPrivateKeyKind::Ed25519(_) => self.signature == SignatureAlgorithm::Ed25519,
119 CryptoPrivateKeyKind::Ecdsa256(_) => self.signature == SignatureAlgorithm::Ecdsa,
120 CryptoPrivateKeyKind::Rsa256(_) => self.signature == SignatureAlgorithm::Rsa,
121 CryptoPrivateKeyKind::Custom(_) => true,
122 }
123 }
124}
125
126pub(crate) fn default_signature_schemes() -> Vec<SignatureHashAlgorithm> {
127 vec![
128 SignatureHashAlgorithm {
129 hash: HashAlgorithm::Sha256,
130 signature: SignatureAlgorithm::Ecdsa,
131 },
132 SignatureHashAlgorithm {
133 hash: HashAlgorithm::Sha384,
134 signature: SignatureAlgorithm::Ecdsa,
135 },
136 SignatureHashAlgorithm {
137 hash: HashAlgorithm::Sha512,
138 signature: SignatureAlgorithm::Ecdsa,
139 },
140 SignatureHashAlgorithm {
141 hash: HashAlgorithm::Sha256,
142 signature: SignatureAlgorithm::Rsa,
143 },
144 SignatureHashAlgorithm {
145 hash: HashAlgorithm::Sha384,
146 signature: SignatureAlgorithm::Rsa,
147 },
148 SignatureHashAlgorithm {
149 hash: HashAlgorithm::Sha512,
150 signature: SignatureAlgorithm::Rsa,
151 },
152 SignatureHashAlgorithm {
153 hash: HashAlgorithm::Ed25519,
154 signature: SignatureAlgorithm::Ed25519,
155 },
156 ]
157}
158
159pub(crate) fn select_signature_scheme(
161 sigs: &[SignatureHashAlgorithm],
162 private_key: &CryptoPrivateKey,
163) -> Result<SignatureHashAlgorithm> {
164 for ss in sigs {
165 if ss.is_compatible(private_key) {
166 return Ok(*ss);
167 }
168 }
169
170 Err(Error::ErrNoAvailableSignatureSchemes)
171}
172
173#[derive(Copy, Clone, Debug, PartialEq, Eq)]
176pub enum SignatureScheme {
178 Pkcs1WithSha256 = 0x0401,
181 Pkcs1WithSha384 = 0x0501,
183 Pkcs1WithSha512 = 0x0601,
185
186 PssWithSha256 = 0x0804,
189 PssWithSha384 = 0x0805,
191 PssWithSha512 = 0x0806,
193
194 EcdsaWithP256AndSha256 = 0x0403,
197 EcdsaWithP384AndSha384 = 0x0503,
199 EcdsaWithP521AndSha512 = 0x0603,
201
202 Ed25519 = 0x0807,
205
206 Pkcs1WithSha1 = 0x0201,
209 EcdsaWithSha1 = 0x0203,
211}
212
213pub(crate) fn parse_signature_schemes(
216 sigs: &[u16],
217 insecure_hashes: bool,
218) -> Result<Vec<SignatureHashAlgorithm>> {
219 if sigs.is_empty() {
220 return Ok(default_signature_schemes());
221 }
222
223 let mut out = vec![];
224 for ss in sigs {
225 let sig: SignatureAlgorithm = ((*ss & 0xFF) as u8).into();
226 if sig == SignatureAlgorithm::Unsupported {
227 return Err(Error::ErrInvalidSignatureAlgorithm);
228 }
229 let h: HashAlgorithm = (((*ss >> 8) & 0xFF) as u8).into();
230 if h == HashAlgorithm::Unsupported || h.invalid() {
231 return Err(Error::ErrInvalidHashAlgorithm);
232 }
233 if h.insecure() && !insecure_hashes {
234 continue;
235 }
236 out.push(SignatureHashAlgorithm {
237 hash: h,
238 signature: sig,
239 })
240 }
241
242 if out.is_empty() {
243 Err(Error::ErrNoAvailableSignatureSchemes)
244 } else {
245 Ok(out)
246 }
247}