| 1 | use alloc::vec::Vec; |
| 2 | use core::fmt::Debug; |
| 3 | |
| 4 | use pki_types::{CertificateDer, ServerName, UnixTime}; |
| 5 | |
| 6 | use crate::enums::SignatureScheme; |
| 7 | use crate::error::{Error, InvalidMessage}; |
| 8 | use crate::msgs::base::PayloadU16; |
| 9 | use crate::msgs::codec::{Codec, Reader}; |
| 10 | use crate::msgs::handshake::DistinguishedName; |
| 11 | |
| 12 | // Marker types. These are used to bind the fact some verification |
| 13 | // (certificate chain or handshake signature) has taken place into |
| 14 | // protocol states. We use this to have the compiler check that there |
| 15 | // are no 'goto fail'-style elisions of important checks before we |
| 16 | // reach the traffic stage. |
| 17 | // |
| 18 | // These types are public, but cannot be directly constructed. This |
| 19 | // means their origins can be precisely determined by looking |
| 20 | // for their `assertion` constructors. |
| 21 | |
| 22 | /// Zero-sized marker type representing verification of a signature. |
| 23 | #[derive (Debug)] |
| 24 | pub struct HandshakeSignatureValid(()); |
| 25 | |
| 26 | impl HandshakeSignatureValid { |
| 27 | /// Make a `HandshakeSignatureValid` |
| 28 | pub fn assertion() -> Self { |
| 29 | Self(()) |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | #[derive (Debug)] |
| 34 | pub(crate) struct FinishedMessageVerified(()); |
| 35 | |
| 36 | impl FinishedMessageVerified { |
| 37 | pub(crate) fn assertion() -> Self { |
| 38 | Self(()) |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | /// Zero-sized marker type representing verification of a server cert chain. |
| 43 | #[allow (unreachable_pub)] |
| 44 | #[derive (Debug)] |
| 45 | pub struct ServerCertVerified(()); |
| 46 | |
| 47 | #[allow (unreachable_pub)] |
| 48 | impl ServerCertVerified { |
| 49 | /// Make a `ServerCertVerified` |
| 50 | pub fn assertion() -> Self { |
| 51 | Self(()) |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | /// Zero-sized marker type representing verification of a client cert chain. |
| 56 | #[derive (Debug)] |
| 57 | pub struct ClientCertVerified(()); |
| 58 | |
| 59 | impl ClientCertVerified { |
| 60 | /// Make a `ClientCertVerified` |
| 61 | pub fn assertion() -> Self { |
| 62 | Self(()) |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | /// Something that can verify a server certificate chain, and verify |
| 67 | /// signatures made by certificates. |
| 68 | #[allow (unreachable_pub)] |
| 69 | pub trait ServerCertVerifier: Debug + Send + Sync { |
| 70 | /// Verify the end-entity certificate `end_entity` is valid for the |
| 71 | /// hostname `dns_name` and chains to at least one trust anchor. |
| 72 | /// |
| 73 | /// `intermediates` contains all certificates other than `end_entity` that |
| 74 | /// were sent as part of the server's [Certificate] message. It is in the |
| 75 | /// same order that the server sent them and may be empty. |
| 76 | /// |
| 77 | /// Note that none of the certificates have been parsed yet, so it is the responsibility of |
| 78 | /// the implementer to handle invalid data. It is recommended that the implementer returns |
| 79 | /// [`Error::InvalidCertificate(CertificateError::BadEncoding)`] when these cases are encountered. |
| 80 | /// |
| 81 | /// [Certificate]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.4.2 |
| 82 | fn verify_server_cert( |
| 83 | &self, |
| 84 | end_entity: &CertificateDer<'_>, |
| 85 | intermediates: &[CertificateDer<'_>], |
| 86 | server_name: &ServerName<'_>, |
| 87 | ocsp_response: &[u8], |
| 88 | now: UnixTime, |
| 89 | ) -> Result<ServerCertVerified, Error>; |
| 90 | |
| 91 | /// Verify a signature allegedly by the given server certificate. |
| 92 | /// |
| 93 | /// `message` is not hashed, and needs hashing during the verification. |
| 94 | /// The signature and algorithm are within `dss`. `cert` contains the |
| 95 | /// public key to use. |
| 96 | /// |
| 97 | /// `cert` has already been validated by [`ServerCertVerifier::verify_server_cert`]. |
| 98 | /// |
| 99 | /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`. |
| 100 | /// Otherwise, return an error -- rustls will send an alert and abort the |
| 101 | /// connection. |
| 102 | /// |
| 103 | /// This method is only called for TLS1.2 handshakes. Note that, in TLS1.2, |
| 104 | /// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not |
| 105 | /// in fact bound to the specific curve implied in their name. |
| 106 | fn verify_tls12_signature( |
| 107 | &self, |
| 108 | message: &[u8], |
| 109 | cert: &CertificateDer<'_>, |
| 110 | dss: &DigitallySignedStruct, |
| 111 | ) -> Result<HandshakeSignatureValid, Error>; |
| 112 | |
| 113 | /// Verify a signature allegedly by the given server certificate. |
| 114 | /// |
| 115 | /// This method is only called for TLS1.3 handshakes. |
| 116 | /// |
| 117 | /// This method is very similar to `verify_tls12_signature`: but note the |
| 118 | /// tighter ECDSA SignatureScheme semantics -- e.g. `SignatureScheme::ECDSA_NISTP256_SHA256` |
| 119 | /// must only validate signatures using public keys on the right curve -- |
| 120 | /// rustls does not enforce this requirement for you. |
| 121 | /// |
| 122 | /// `cert` has already been validated by [`ServerCertVerifier::verify_server_cert`]. |
| 123 | /// |
| 124 | /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`. |
| 125 | /// Otherwise, return an error -- rustls will send an alert and abort the |
| 126 | /// connection. |
| 127 | fn verify_tls13_signature( |
| 128 | &self, |
| 129 | message: &[u8], |
| 130 | cert: &CertificateDer<'_>, |
| 131 | dss: &DigitallySignedStruct, |
| 132 | ) -> Result<HandshakeSignatureValid, Error>; |
| 133 | |
| 134 | /// Return the list of SignatureSchemes that this verifier will handle, |
| 135 | /// in `verify_tls12_signature` and `verify_tls13_signature` calls. |
| 136 | /// |
| 137 | /// This should be in priority order, with the most preferred first. |
| 138 | fn supported_verify_schemes(&self) -> Vec<SignatureScheme>; |
| 139 | |
| 140 | /// Returns whether this verifier requires raw public keys as defined |
| 141 | /// in [RFC 7250](https://tools.ietf.org/html/rfc7250). |
| 142 | fn requires_raw_public_keys(&self) -> bool { |
| 143 | false |
| 144 | } |
| 145 | |
| 146 | /// Return the [`DistinguishedName`]s of certificate authorities that this verifier trusts. |
| 147 | /// |
| 148 | /// If specified, will be sent as the [`certificate_authorities`] extension in ClientHello. |
| 149 | /// Note that this is only applicable to TLS 1.3. |
| 150 | /// |
| 151 | /// [`certificate_authorities`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4 |
| 152 | fn root_hint_subjects(&self) -> Option<&[DistinguishedName]> { |
| 153 | None |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | /// Something that can verify a client certificate chain |
| 158 | #[allow (unreachable_pub)] |
| 159 | pub trait ClientCertVerifier: Debug + Send + Sync { |
| 160 | /// Returns `true` to enable the server to request a client certificate and |
| 161 | /// `false` to skip requesting a client certificate. Defaults to `true`. |
| 162 | fn offer_client_auth(&self) -> bool { |
| 163 | true |
| 164 | } |
| 165 | |
| 166 | /// Return `true` to require a client certificate and `false` to make |
| 167 | /// client authentication optional. |
| 168 | /// Defaults to `self.offer_client_auth()`. |
| 169 | fn client_auth_mandatory(&self) -> bool { |
| 170 | self.offer_client_auth() |
| 171 | } |
| 172 | |
| 173 | /// Returns the [`DistinguishedName`] [subjects] that the server will hint to clients to |
| 174 | /// identify acceptable authentication trust anchors. |
| 175 | /// |
| 176 | /// These hint values help the client pick a client certificate it believes the server will |
| 177 | /// accept. The hints must be DER-encoded X.500 distinguished names, per [RFC 5280 A.1]. They |
| 178 | /// are sent in the [`certificate_authorities`] extension of a [`CertificateRequest`] message |
| 179 | /// when [ClientCertVerifier::offer_client_auth] is true. When an empty list is sent the client |
| 180 | /// should always provide a client certificate if it has one. |
| 181 | /// |
| 182 | /// Generally this list should contain the [`DistinguishedName`] of each root trust |
| 183 | /// anchor in the root cert store that the server is configured to use for authenticating |
| 184 | /// presented client certificates. |
| 185 | /// |
| 186 | /// In some circumstances this list may be customized to include [`DistinguishedName`] entries |
| 187 | /// that do not correspond to a trust anchor in the server's root cert store. For example, |
| 188 | /// the server may be configured to trust a root CA that cross-signed an issuer certificate |
| 189 | /// that the client considers a trust anchor. From the server's perspective the cross-signed |
| 190 | /// certificate is an intermediate, and not present in the server's root cert store. The client |
| 191 | /// may have the cross-signed certificate configured as a trust anchor, and be unaware of the |
| 192 | /// root CA that cross-signed it. If the server's hints list only contained the subjects of the |
| 193 | /// server's root store the client would consider a client certificate issued by the cross-signed |
| 194 | /// issuer unacceptable, since its subject was not hinted. To avoid this circumstance the server |
| 195 | /// should customize the hints list to include the subject of the cross-signed issuer in addition |
| 196 | /// to the subjects from the root cert store. |
| 197 | /// |
| 198 | /// [subjects]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 |
| 199 | /// [RFC 5280 A.1]: https://www.rfc-editor.org/rfc/rfc5280#appendix-A.1 |
| 200 | /// [`CertificateRequest`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.3.2 |
| 201 | /// [`certificate_authorities`]: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.4 |
| 202 | fn root_hint_subjects(&self) -> &[DistinguishedName]; |
| 203 | |
| 204 | /// Verify the end-entity certificate `end_entity` is valid, acceptable, |
| 205 | /// and chains to at least one of the trust anchors trusted by |
| 206 | /// this verifier. |
| 207 | /// |
| 208 | /// `intermediates` contains the intermediate certificates the |
| 209 | /// client sent along with the end-entity certificate; it is in the same |
| 210 | /// order that the peer sent them and may be empty. |
| 211 | /// |
| 212 | /// Note that none of the certificates have been parsed yet, so it is the responsibility of |
| 213 | /// the implementer to handle invalid data. It is recommended that the implementer returns |
| 214 | /// an [InvalidCertificate] error with the [BadEncoding] variant when these cases are encountered. |
| 215 | /// |
| 216 | /// [InvalidCertificate]: Error#variant.InvalidCertificate |
| 217 | /// [BadEncoding]: crate::CertificateError#variant.BadEncoding |
| 218 | fn verify_client_cert( |
| 219 | &self, |
| 220 | end_entity: &CertificateDer<'_>, |
| 221 | intermediates: &[CertificateDer<'_>], |
| 222 | now: UnixTime, |
| 223 | ) -> Result<ClientCertVerified, Error>; |
| 224 | |
| 225 | /// Verify a signature allegedly by the given client certificate. |
| 226 | /// |
| 227 | /// `message` is not hashed, and needs hashing during the verification. |
| 228 | /// The signature and algorithm are within `dss`. `cert` contains the |
| 229 | /// public key to use. |
| 230 | /// |
| 231 | /// `cert` has already been validated by [`ClientCertVerifier::verify_client_cert`]. |
| 232 | /// |
| 233 | /// If and only if the signature is valid, return `Ok(HandshakeSignatureValid)`. |
| 234 | /// Otherwise, return an error -- rustls will send an alert and abort the |
| 235 | /// connection. |
| 236 | /// |
| 237 | /// This method is only called for TLS1.2 handshakes. Note that, in TLS1.2, |
| 238 | /// SignatureSchemes such as `SignatureScheme::ECDSA_NISTP256_SHA256` are not |
| 239 | /// in fact bound to the specific curve implied in their name. |
| 240 | fn verify_tls12_signature( |
| 241 | &self, |
| 242 | message: &[u8], |
| 243 | cert: &CertificateDer<'_>, |
| 244 | dss: &DigitallySignedStruct, |
| 245 | ) -> Result<HandshakeSignatureValid, Error>; |
| 246 | |
| 247 | /// Verify a signature allegedly by the given client certificate. |
| 248 | /// |
| 249 | /// This method is only called for TLS1.3 handshakes. |
| 250 | /// |
| 251 | /// This method is very similar to `verify_tls12_signature`, but note the |
| 252 | /// tighter ECDSA SignatureScheme semantics in TLS 1.3. For example, |
| 253 | /// `SignatureScheme::ECDSA_NISTP256_SHA256` |
| 254 | /// must only validate signatures using public keys on the right curve -- |
| 255 | /// rustls does not enforce this requirement for you. |
| 256 | fn verify_tls13_signature( |
| 257 | &self, |
| 258 | message: &[u8], |
| 259 | cert: &CertificateDer<'_>, |
| 260 | dss: &DigitallySignedStruct, |
| 261 | ) -> Result<HandshakeSignatureValid, Error>; |
| 262 | |
| 263 | /// Return the list of SignatureSchemes that this verifier will handle, |
| 264 | /// in `verify_tls12_signature` and `verify_tls13_signature` calls. |
| 265 | /// |
| 266 | /// This should be in priority order, with the most preferred first. |
| 267 | fn supported_verify_schemes(&self) -> Vec<SignatureScheme>; |
| 268 | |
| 269 | /// Returns whether this verifier requires raw public keys as defined |
| 270 | /// in [RFC 7250](https://tools.ietf.org/html/rfc7250). |
| 271 | fn requires_raw_public_keys(&self) -> bool { |
| 272 | false |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | /// Turns off client authentication. |
| 277 | /// |
| 278 | /// In contrast to using |
| 279 | /// `WebPkiClientVerifier::builder(roots).allow_unauthenticated().build()`, the `NoClientAuth` |
| 280 | /// `ClientCertVerifier` will not offer client authentication at all, vs offering but not |
| 281 | /// requiring it. |
| 282 | #[derive (Debug)] |
| 283 | pub struct NoClientAuth; |
| 284 | |
| 285 | impl ClientCertVerifier for NoClientAuth { |
| 286 | fn offer_client_auth(&self) -> bool { |
| 287 | false |
| 288 | } |
| 289 | |
| 290 | fn root_hint_subjects(&self) -> &[DistinguishedName] { |
| 291 | unimplemented!(); |
| 292 | } |
| 293 | |
| 294 | fn verify_client_cert( |
| 295 | &self, |
| 296 | _end_entity: &CertificateDer<'_>, |
| 297 | _intermediates: &[CertificateDer<'_>], |
| 298 | _now: UnixTime, |
| 299 | ) -> Result<ClientCertVerified, Error> { |
| 300 | unimplemented!(); |
| 301 | } |
| 302 | |
| 303 | fn verify_tls12_signature( |
| 304 | &self, |
| 305 | _message: &[u8], |
| 306 | _cert: &CertificateDer<'_>, |
| 307 | _dss: &DigitallySignedStruct, |
| 308 | ) -> Result<HandshakeSignatureValid, Error> { |
| 309 | unimplemented!(); |
| 310 | } |
| 311 | |
| 312 | fn verify_tls13_signature( |
| 313 | &self, |
| 314 | _message: &[u8], |
| 315 | _cert: &CertificateDer<'_>, |
| 316 | _dss: &DigitallySignedStruct, |
| 317 | ) -> Result<HandshakeSignatureValid, Error> { |
| 318 | unimplemented!(); |
| 319 | } |
| 320 | |
| 321 | fn supported_verify_schemes(&self) -> Vec<SignatureScheme> { |
| 322 | unimplemented!(); |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | /// This type combines a [`SignatureScheme`] and a signature payload produced with that scheme. |
| 327 | #[derive (Debug, Clone)] |
| 328 | pub struct DigitallySignedStruct { |
| 329 | /// The [`SignatureScheme`] used to produce the signature. |
| 330 | pub scheme: SignatureScheme, |
| 331 | sig: PayloadU16, |
| 332 | } |
| 333 | |
| 334 | impl DigitallySignedStruct { |
| 335 | pub(crate) fn new(scheme: SignatureScheme, sig: Vec<u8>) -> Self { |
| 336 | Self { |
| 337 | scheme, |
| 338 | sig: PayloadU16::new(bytes:sig), |
| 339 | } |
| 340 | } |
| 341 | |
| 342 | /// Get the signature. |
| 343 | pub fn signature(&self) -> &[u8] { |
| 344 | &self.sig.0 |
| 345 | } |
| 346 | } |
| 347 | |
| 348 | impl Codec<'_> for DigitallySignedStruct { |
| 349 | fn encode(&self, bytes: &mut Vec<u8>) { |
| 350 | self.scheme.encode(bytes); |
| 351 | self.sig.encode(bytes); |
| 352 | } |
| 353 | |
| 354 | fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> { |
| 355 | let scheme: SignatureScheme = SignatureScheme::read(r)?; |
| 356 | let sig: PayloadU16 = PayloadU16::read(r)?; |
| 357 | |
| 358 | Ok(Self { scheme, sig }) |
| 359 | } |
| 360 | } |
| 361 | |
| 362 | #[test ] |
| 363 | fn assertions_are_debug() { |
| 364 | use std::format; |
| 365 | |
| 366 | assert_eq!( |
| 367 | format!("{:?}" , ClientCertVerified::assertion()), |
| 368 | "ClientCertVerified(())" |
| 369 | ); |
| 370 | assert_eq!( |
| 371 | format!("{:?}" , HandshakeSignatureValid::assertion()), |
| 372 | "HandshakeSignatureValid(())" |
| 373 | ); |
| 374 | assert_eq!( |
| 375 | format!("{:?}" , FinishedMessageVerified::assertion()), |
| 376 | "FinishedMessageVerified(())" |
| 377 | ); |
| 378 | assert_eq!( |
| 379 | format!("{:?}" , ServerCertVerified::assertion()), |
| 380 | "ServerCertVerified(())" |
| 381 | ); |
| 382 | } |
| 383 | |