verdict_parser/asn1/
octet_string.rs1use super::*;
2use vstd::prelude::*;
3
4verus! {
5
6#[derive(Debug, View)]
8pub struct OctetString;
9
10asn1_tagged!(OctetString, tag_of!(OCTET_STRING));
11
12impl SpecCombinator for OctetString {
13 type SpecResult = Seq<u8>;
14
15 closed spec fn spec_parse(&self, s: Seq<u8>) -> Result<(usize, Self::SpecResult), ()> {
16 match new_spec_octet_string_inner().spec_parse(s) {
17 Ok((len, (_, v))) => Ok((len, v)),
18 Err(..) => Err(()),
19 }
20 }
21
22 proof fn spec_parse_wf(&self, s: Seq<u8>) {
23 new_spec_octet_string_inner().spec_parse_wf(s)
24 }
25
26 closed spec fn spec_serialize(&self, v: Self::SpecResult) -> Result<Seq<u8>, ()> {
27 new_spec_octet_string_inner().spec_serialize((v.len() as LengthValue, v))
28 }
29}
30
31impl SecureSpecCombinator for OctetString {
32 open spec fn is_prefix_secure() -> bool {
33 true
34 }
35
36 proof fn theorem_serialize_parse_roundtrip(&self, v: Self::SpecResult) {
37 new_spec_octet_string_inner().theorem_serialize_parse_roundtrip((v.len() as LengthValue, v));
38 }
39
40 proof fn theorem_parse_serialize_roundtrip(&self, buf: Seq<u8>) {
41 new_spec_octet_string_inner().theorem_parse_serialize_roundtrip(buf);
42 }
43
44 proof fn lemma_prefix_secure(&self, s1: Seq<u8>, s2: Seq<u8>) {
45 new_spec_octet_string_inner().lemma_prefix_secure(s1, s2);
46 }
47}
48
49impl Combinator for OctetString {
50 type Result<'a> = &'a [u8];
51 type Owned = Vec<u8>;
52
53 closed spec fn spec_length(&self) -> Option<usize> {
54 None
55 }
56
57 fn length(&self) -> Option<usize> {
58 None
59 }
60
61 #[inline(always)]
62 fn parse<'a>(&self, s: &'a [u8]) -> (res: Result<(usize, Self::Result<'a>), ParseError>) {
63 let (len, (_, v)) = new_octet_string_inner().parse(s)?;
64 Ok((len, v))
65 }
66
67 #[inline(always)]
68 fn serialize(&self, v: Self::Result<'_>, data: &mut Vec<u8>, pos: usize) -> (res: Result<usize, SerializeError>) {
69 new_octet_string_inner().serialize((v.len() as LengthValue, v), data, pos)
70 }
71}
72
73struct BytesCont;
75
76impl Continuation for BytesCont {
77 type Input<'a> = LengthValue;
78 type Output = Bytes;
79
80 #[inline(always)]
81 fn apply<'a>(&self, i: Self::Input<'a>) -> (o: Self::Output) {
82 Bytes(i as usize)
83 }
84
85 closed spec fn requires<'a>(&self, i: Self::Input<'a>) -> bool {
86 true
87 }
88
89 closed spec fn ensures<'a>(&self, i: Self::Input<'a>, o: Self::Output) -> bool {
90 &&& o == Bytes(i as usize)
91 &&& o.parse_requires()
92 &&& o.serialize_requires()
93 }
94}
95
96#[allow(dead_code)]
97type SpecOctetStringInner = SpecDepend<Length, Bytes>;
98type OctetStringInner = Depend<Length, Bytes, BytesCont>;
99
100closed spec fn new_spec_octet_string_inner() -> SpecOctetStringInner {
101 SpecDepend {
102 fst: Length,
103 snd: |l| {
104 Bytes(l as usize)
105 },
106 }
107}
108
109closed spec fn spec_new_octet_string_inner() -> OctetStringInner
110{
111 Depend {
112 fst: Length,
113 snd: BytesCont,
114 spec_snd: Ghost(|l| {
115 Bytes(l as usize)
116 }),
117 }
118}
119
120#[inline(always)]
121fn new_octet_string_inner() -> (res: OctetStringInner)
122 ensures
123 res@ == new_spec_octet_string_inner(),
124 res == spec_new_octet_string_inner(),
125{
126 Depend {
127 fst: Length,
128 snd: BytesCont,
129 spec_snd: Ghost(|l| {
130 Bytes(l as usize)
131 }),
132 }
133}
134
135}
136
137#[cfg(test)]
138mod test {
139 use super::*;
140 use der::Encode;
141
142 fn serialize_octet_string(v: &[u8]) -> Result<Vec<u8>, SerializeError> {
143 let mut data = vec![0; v.len() + 10];
144 data[0] = 0x04; let len = OctetString.serialize(v, &mut data, 1)?;
146 data.truncate(len + 1);
147 Ok(data)
148 }
149
150 #[test]
151 fn diff_with_der() {
152 let diff = |bytes: &[u8]| {
153 let res1 = serialize_octet_string(bytes).map_err(|_| ());
154 let res2 = der::asn1::OctetString::new(bytes)
155 .unwrap()
156 .to_der()
157 .map_err(|_| ());
158 assert_eq!(res1, res2);
159 };
160
161 diff(&[]);
162 diff(&[0]);
163 diff(&[0; 256]);
164 diff(&[0; 257]);
165 diff(&[0; 65536]);
166 }
167}