/rust/git/checkouts/nss-rs-71e20fe79ef91440/9b94ca3/src/replay.rs
Line | Count | Source |
1 | | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
2 | | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
3 | | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
4 | | // option. This file may not be copied, modified, or distributed |
5 | | // except according to those terms. |
6 | | |
7 | | use std::{ |
8 | | os::raw::c_uint, |
9 | | ptr::null_mut, |
10 | | time::{Duration, Instant}, |
11 | | }; |
12 | | |
13 | | use crate::{ |
14 | | err::Res, |
15 | | prio::PRFileDesc, |
16 | | time::{Interval, PRTime, Time}, |
17 | | }; |
18 | | |
19 | | // This is an opaque struct in NSS. |
20 | | pub enum SSLAntiReplayContext {} |
21 | | |
22 | | experimental_api!(SSL_CreateAntiReplayContext( |
23 | | now: PRTime, |
24 | | window: PRTime, |
25 | | k: c_uint, |
26 | | bits: c_uint, |
27 | | ctx: *mut *mut SSLAntiReplayContext, |
28 | | )); |
29 | | experimental_api!(SSL_ReleaseAntiReplayContext(ctx: *mut SSLAntiReplayContext)); |
30 | | experimental_api!(SSL_SetAntiReplayContext( |
31 | | fd: *mut PRFileDesc, |
32 | | ctx: *mut SSLAntiReplayContext, |
33 | | )); |
34 | | |
35 | | scoped_ptr!( |
36 | | AntiReplayContext, |
37 | | SSLAntiReplayContext, |
38 | | SSL_ReleaseAntiReplayContext |
39 | | ); |
40 | | |
41 | | /// `AntiReplay` is used by servers when processing 0-RTT handshakes. |
42 | | /// |
43 | | /// It limits the exposure of servers to replay attack by rejecting 0-RTT |
44 | | /// if it appears to be a replay. There is a false-positive rate that can be |
45 | | /// managed by tuning the parameters used to create the context. |
46 | | pub struct AntiReplay { |
47 | | ctx: AntiReplayContext, |
48 | | } |
49 | | |
50 | | impl AntiReplay { |
51 | | /// Make a new anti-replay context. |
52 | | /// See the documentation in NSS for advice on how to set these values. |
53 | | /// |
54 | | /// # Errors |
55 | | /// |
56 | | /// Returns an error if `now` is in the past relative to our baseline or |
57 | | /// NSS is unable to generate an anti-replay context. |
58 | 1.28k | pub fn new(now: Instant, window: Duration, k: usize, bits: usize) -> Res<Self> { |
59 | 1.28k | let mut ctx: *mut SSLAntiReplayContext = null_mut(); |
60 | | unsafe { |
61 | 1.28k | SSL_CreateAntiReplayContext( |
62 | 1.28k | Time::from(now).try_into()?, |
63 | 1.28k | Interval::from(window).try_into()?, |
64 | 1.28k | c_uint::try_from(k)?, |
65 | 1.28k | c_uint::try_from(bits)?, |
66 | 1.28k | &raw mut ctx, |
67 | | ) |
68 | 0 | }?; |
69 | | |
70 | | Ok(Self { |
71 | 1.28k | ctx: AntiReplayContext::from_ptr(ctx)?, |
72 | | }) |
73 | 1.28k | } |
74 | | |
75 | | /// Configure the provided socket with this anti-replay context. |
76 | 1.28k | pub(crate) fn config_socket(&self, fd: *mut PRFileDesc) -> Res<()> { |
77 | 1.28k | unsafe { SSL_SetAntiReplayContext(fd, *self.ctx) } |
78 | 1.28k | } |
79 | | } |
80 | | |
81 | | #[cfg(test)] |
82 | | #[cfg_attr(coverage_nightly, coverage(off))] |
83 | | mod tests { |
84 | | use std::time::Duration; |
85 | | |
86 | | #[test] |
87 | | fn creation() { |
88 | | test_fixture::fixture_init(); |
89 | | for (k, bits, expected) in [(7, 8, true), (usize::MAX, 3, false), (1, usize::MAX, false)] { |
90 | | let res = crate::AntiReplay::new(test_fixture::now(), Duration::from_secs(10), k, bits); |
91 | | assert_eq!(res.is_ok(), expected); |
92 | | } |
93 | | } |
94 | | } |