1#![forbid(unsafe_code)]
2
3pub mod asn1;
4mod common;
5pub mod x509;
6
7pub use common::*;
8
9use vstd::prelude::*;
10
11verus! {
12 pub closed spec fn spec_parse_x509_der(der: Seq<u8>) -> Option<x509::SpecCertificateValue> {
14 match x509::Certificate.spec_parse(der) {
15 Ok((n, cert)) if n == der.len() => Some(cert),
16 _ => None,
17 }
18 }
19
20 pub closed spec fn spec_decode_base64(base64: Seq<u8>) -> Option<Seq<u8>> {
22 match Base64.spec_parse(base64) {
23 Ok((n, bytes)) if n == base64.len() => Some(bytes),
24 _ => None,
25 }
26 }
27
28 pub open spec fn spec_parse_x509_base64(base64: Seq<u8>) -> Option<x509::SpecCertificateValue> {
30 match spec_decode_base64(base64) {
31 Some(der) => spec_parse_x509_der(der),
32 None => None,
33 }
34 }
35
36 pub fn parse_x509_der<'a>(bytes: &'a [u8]) -> (res: Result<x509::CertificateValue<'a>, ParseError>)
44 ensures
45 res matches Ok(res) ==> {
46 &&& spec_parse_x509_der(bytes@) == Some(res@)
48
49 &&& forall |other: Seq<u8>| {
51 &&& other.len() <= usize::MAX
52 &&& #[trigger] spec_parse_x509_der(other) == Some(res@)
53 } ==> other == bytes@
54
55 &&& forall |suffix: Seq<u8>| {
57 &&& suffix.len() != 0
58 &&& bytes@.len() + suffix.len() <= usize::MAX
59 } ==> #[trigger] spec_parse_x509_der(bytes@ + suffix) is None
60 },
61
62 res is Err ==> spec_parse_x509_der(bytes@) is None,
64 {
65 let (n, cert) = x509::Certificate.parse(bytes)?;
66 if n != bytes.len() {
67 return Err(ParseError::Other("trailing bytes in certificate".to_string()));
68 }
69
70 proof {
71 let (n, spec_res) = x509::Certificate.spec_parse(bytes@).unwrap();
72
73 assert forall |other: Seq<u8>| {
74 &&& other.len() <= usize::MAX
75 &&& #[trigger] spec_parse_x509_der(other) == Some(cert@)
76 } implies other == bytes@ by {
77 let (m, other_res) = x509::Certificate.spec_parse(other).unwrap();
78 let other_ser = x509::Certificate.spec_serialize(other_res).unwrap();
79 let spec_ser = x509::Certificate.spec_serialize(spec_res).unwrap();
80
81 x509::Certificate.theorem_parse_serialize_roundtrip(other);
82 x509::Certificate.theorem_parse_serialize_roundtrip(bytes@);
83
84 assert(other_ser == other);
85 assert(other == spec_ser);
86 assert(spec_ser == bytes@);
87 }
88
89 assert forall |suffix: Seq<u8>|{
90 &&& suffix.len() != 0
91 &&& bytes@.len() + suffix.len() <= usize::MAX
92 } implies #[trigger] spec_parse_x509_der(bytes@ + suffix) is None by {
93 x509::Certificate.lemma_prefix_secure(bytes@, suffix);
94 }
95 }
96
97 Ok(cert)
98 }
99
100 pub fn decode_base64(encoded: &[u8]) -> (res: Result<Vec<u8>, ParseError>)
107 ensures
108 res matches Ok(res) ==> {
109 &&& spec_decode_base64(encoded@) == Some(res@)
111
112 &&& forall |other: Seq<u8>| {
114 &&& other.len() <= usize::MAX
115 &&& #[trigger] spec_decode_base64(other) == Some(res@)
116 } ==> other == encoded@
117 },
118
119 res is Err ==> spec_decode_base64(encoded@) is None,
121 {
122 let (n, bytes) = Base64.parse(encoded)?;
123
124 if n != encoded.len() {
125 return Err(ParseError::Other("trailing bytes in base64".to_string()));
126 }
127
128 assert(encoded.len() <= usize::MAX);
129 proof {
130 let (n, spec_res) = Base64.spec_parse(encoded@).unwrap();
131
132 assert forall |other: Seq<u8>| {
133 &&& other.len() <= usize::MAX
134 &&& #[trigger] spec_decode_base64(other) == Some(bytes@)
135 } implies other == encoded@ by {
136 let (_, other_res) = Base64.spec_parse(other).unwrap();
137 let other_ser = Base64.spec_serialize(other_res).unwrap();
138 let spec_ser = Base64.spec_serialize(spec_res).unwrap();
139
140 Base64.theorem_parse_serialize_roundtrip(other);
141 Base64.theorem_parse_serialize_roundtrip(encoded@);
142
143 assert(other_ser == other);
144 assert(other == spec_ser);
145 assert(spec_ser == encoded@);
146 }
147 }
148
149 Ok(bytes)
150 }
151}