1use std::convert::TryFrom;
2
3pub use super::{Error, ReportAuthorizationKey, TemporaryContactKey, TemporaryContactNumber};
4
5#[derive(Copy, Clone, Debug, Eq, PartialEq)]
7#[repr(u8)]
8pub enum MemoType {
9 CoEpiV1 = 0,
11 CovidWatchV1 = 1,
13 Reserved = 0xff,
15}
16
17#[derive(Clone, Debug)]
19pub struct Report {
20 pub(crate) rvk: ed25519_zebra::PublicKeyBytes,
21 pub(crate) tck_bytes: [u8; 32],
22 pub(crate) j_1: u16,
24 pub(crate) j_2: u16,
25 pub(crate) memo_type: MemoType,
26 pub(crate) memo_data: Vec<u8>,
27}
28
29impl Report {
30 pub fn memo_type(&self) -> MemoType {
32 self.memo_type
33 }
34
35 pub fn memo_data(&self) -> &[u8] {
37 &self.memo_data
38 }
39
40 pub fn temporary_contact_numbers(&self) -> impl Iterator<Item = TemporaryContactNumber> {
42 let mut tck = TemporaryContactKey {
43 index: self.j_1 - 1,
45 rvk: self.rvk,
46 tck_bytes: self.tck_bytes,
47 };
48 tck = tck.ratchet().expect("j_1 - 1 < j_1 <= u16::MAX");
50
51 (self.j_1..self.j_2).map(move |_| {
52 let tcn = tck.temporary_contact_number();
53 tck = tck
54 .ratchet()
55 .expect("we do not ratchet past j_2 <= u16::MAX");
56 tcn
57 })
58 }
59}
60
61impl ReportAuthorizationKey {
62 pub fn create_report(
81 &self,
82 memo_type: MemoType,
83 memo_data: Vec<u8>,
84 j_1: u16,
85 j_2: u16,
86 ) -> Result<SignedReport, Error> {
87 let j_1 = if j_1 == 0 { 1 } else { j_1 };
89
90 let mut tck = self.tck_0();
94 for _ in 0..(j_1 - 1) {
95 tck = tck.ratchet().expect("j_1 - 1 < u16::MAX");
96 }
97
98 let report = Report {
99 rvk: ed25519_zebra::PublicKeyBytes::from(&self.rak),
100 tck_bytes: tck.tck_bytes,
101 j_1,
103 j_2,
104 memo_type,
105 memo_data,
106 };
107
108 use std::io::Cursor;
109 let mut report_bytes = Vec::with_capacity(report.size_hint());
110 report.write(Cursor::new(&mut report_bytes))?;
111 let sig = self.rak.sign(&report_bytes);
112
113 Ok(SignedReport { report, sig })
114 }
115}
116
117#[derive(Clone, Debug)]
119pub struct SignedReport {
120 pub(crate) report: Report,
121 pub(crate) sig: ed25519_zebra::Signature,
122}
123
124impl SignedReport {
125 pub fn verify(self) -> Result<Report, Error> {
127 use std::io::Cursor;
128 let mut report_bytes = Vec::with_capacity(self.report.size_hint());
129 self.report.write(Cursor::new(&mut report_bytes))?;
130
131 match ed25519_zebra::PublicKey::try_from(self.report.rvk)
132 .and_then(|pk| pk.verify(&self.sig, &report_bytes))
133 {
134 Ok(_) => Ok(self.report),
135 Err(_) => Err(Error::ReportVerificationFailed),
136 }
137 }
138}