webrtc_dtls/signature_hash_algorithm/
mod.rs1#[cfg(test)]
2mod signature_hash_algorithm_test;
3
4use std::fmt;
5
6use crate::crypto::*;
7use crate::error::*;
8
9#[derive(Copy, Clone, Debug, PartialEq, Eq)]
13pub enum HashAlgorithm {
14 Md2 = 0, Md5 = 1, Sha1 = 2, Sha224 = 3,
18 Sha256 = 4,
19 Sha384 = 5,
20 Sha512 = 6,
21 Ed25519 = 8,
22 Unsupported,
23}
24
25impl From<u8> for HashAlgorithm {
26 fn from(val: u8) -> Self {
27 match val {
28 0 => HashAlgorithm::Md2,
29 1 => HashAlgorithm::Md5,
30 2 => HashAlgorithm::Sha1,
31 3 => HashAlgorithm::Sha224,
32 4 => HashAlgorithm::Sha256,
33 5 => HashAlgorithm::Sha384,
34 6 => HashAlgorithm::Sha512,
35 8 => HashAlgorithm::Ed25519,
36 _ => HashAlgorithm::Unsupported,
37 }
38 }
39}
40
41impl fmt::Display for HashAlgorithm {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 match *self {
44 HashAlgorithm::Md2 => write!(f, "md2"),
45 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"),
53 }
54 }
55}
56
57impl HashAlgorithm {
58 pub(crate) fn insecure(&self) -> bool {
59 matches!(
60 *self,
61 HashAlgorithm::Md2 | HashAlgorithm::Md5 | HashAlgorithm::Sha1
62 )
63 }
64
65 pub(crate) fn invalid(&self) -> bool {
66 matches!(*self, HashAlgorithm::Md2)
67 }
68}
69
70#[derive(Copy, Clone, Debug, PartialEq, Eq)]
72pub enum SignatureAlgorithm {
73 Rsa = 1,
74 Ecdsa = 3,
75 Ed25519 = 7,
76 Unsupported,
77}
78
79impl From<u8> for SignatureAlgorithm {
80 fn from(val: u8) -> Self {
81 match val {
82 1 => SignatureAlgorithm::Rsa,
83 3 => SignatureAlgorithm::Ecdsa,
84 7 => SignatureAlgorithm::Ed25519,
85 _ => SignatureAlgorithm::Unsupported,
86 }
87 }
88}
89
90#[derive(Copy, Clone, Debug, PartialEq, Eq)]
91pub struct SignatureHashAlgorithm {
92 pub hash: HashAlgorithm,
93 pub signature: SignatureAlgorithm,
94}
95
96impl SignatureHashAlgorithm {
97 pub(crate) fn is_compatible(&self, private_key: &CryptoPrivateKey) -> bool {
99 match &private_key.kind {
100 CryptoPrivateKeyKind::Ed25519(_) => self.signature == SignatureAlgorithm::Ed25519,
101 CryptoPrivateKeyKind::Ecdsa256(_) => self.signature == SignatureAlgorithm::Ecdsa,
102 CryptoPrivateKeyKind::Rsa256(_) => self.signature == SignatureAlgorithm::Rsa,
103 }
104 }
105}
106
107pub(crate) fn default_signature_schemes() -> Vec<SignatureHashAlgorithm> {
108 vec![
109 SignatureHashAlgorithm {
110 hash: HashAlgorithm::Sha256,
111 signature: SignatureAlgorithm::Ecdsa,
112 },
113 SignatureHashAlgorithm {
114 hash: HashAlgorithm::Sha384,
115 signature: SignatureAlgorithm::Ecdsa,
116 },
117 SignatureHashAlgorithm {
118 hash: HashAlgorithm::Sha512,
119 signature: SignatureAlgorithm::Ecdsa,
120 },
121 SignatureHashAlgorithm {
122 hash: HashAlgorithm::Sha256,
123 signature: SignatureAlgorithm::Rsa,
124 },
125 SignatureHashAlgorithm {
126 hash: HashAlgorithm::Sha384,
127 signature: SignatureAlgorithm::Rsa,
128 },
129 SignatureHashAlgorithm {
130 hash: HashAlgorithm::Sha512,
131 signature: SignatureAlgorithm::Rsa,
132 },
133 SignatureHashAlgorithm {
134 hash: HashAlgorithm::Ed25519,
135 signature: SignatureAlgorithm::Ed25519,
136 },
137 ]
138}
139
140pub(crate) fn select_signature_scheme(
142 sigs: &[SignatureHashAlgorithm],
143 private_key: &CryptoPrivateKey,
144) -> Result<SignatureHashAlgorithm> {
145 for ss in sigs {
146 if ss.is_compatible(private_key) {
147 return Ok(*ss);
148 }
149 }
150
151 Err(Error::ErrNoAvailableSignatureSchemes)
152}
153
154#[derive(Copy, Clone, Debug, PartialEq, Eq)]
157pub enum SignatureScheme {
158 Pkcs1WithSha256 = 0x0401,
160 Pkcs1WithSha384 = 0x0501,
161 Pkcs1WithSha512 = 0x0601,
162
163 PssWithSha256 = 0x0804,
165 PssWithSha384 = 0x0805,
166 PssWithSha512 = 0x0806,
167
168 EcdsaWithP256AndSha256 = 0x0403,
170 EcdsaWithP384AndSha384 = 0x0503,
171 EcdsaWithP521AndSha512 = 0x0603,
172
173 Ed25519 = 0x0807,
175
176 Pkcs1WithSha1 = 0x0201,
178 EcdsaWithSha1 = 0x0203,
179}
180
181pub(crate) fn parse_signature_schemes(
184 sigs: &[u16],
185 insecure_hashes: bool,
186) -> Result<Vec<SignatureHashAlgorithm>> {
187 if sigs.is_empty() {
188 return Ok(default_signature_schemes());
189 }
190
191 let mut out = vec![];
192 for ss in sigs {
193 let sig: SignatureAlgorithm = ((*ss & 0xFF) as u8).into();
194 if sig == SignatureAlgorithm::Unsupported {
195 return Err(Error::ErrInvalidSignatureAlgorithm);
196 }
197 let h: HashAlgorithm = (((*ss >> 8) & 0xFF) as u8).into();
198 if h == HashAlgorithm::Unsupported || h.invalid() {
199 return Err(Error::ErrInvalidHashAlgorithm);
200 }
201 if h.insecure() && !insecure_hashes {
202 continue;
203 }
204 out.push(SignatureHashAlgorithm {
205 hash: h,
206 signature: sig,
207 })
208 }
209
210 if out.is_empty() {
211 Err(Error::ErrNoAvailableSignatureSchemes)
212 } else {
213 Ok(out)
214 }
215}