opcua_core/comms/
security_header.rs1use std::io::{Read, Write};
11
12use opcua_types::{
13 ByteString, DecodingOptions, EncodingResult, Error, SimpleBinaryDecodable,
14 SimpleBinaryEncodable, UAString,
15};
16
17use opcua_types::{constants, status_code::StatusCode};
18
19use opcua_crypto::{SecurityPolicy, Thumbprint, X509};
20
21#[derive(Debug, Clone, PartialEq)]
24pub enum SecurityHeader {
25 Asymmetric(AsymmetricSecurityHeader),
27 Symmetric(SymmetricSecurityHeader),
29}
30
31impl SimpleBinaryEncodable for SecurityHeader {
32 fn byte_len(&self) -> usize {
33 match self {
34 SecurityHeader::Asymmetric(value) => value.byte_len(),
35 SecurityHeader::Symmetric(value) => value.byte_len(),
36 }
37 }
38
39 fn encode<S: Write + ?Sized>(&self, stream: &mut S) -> EncodingResult<()> {
40 match self {
41 SecurityHeader::Asymmetric(value) => value.encode(stream),
42 SecurityHeader::Symmetric(value) => value.encode(stream),
43 }
44 }
45}
46
47impl SecurityHeader {
48 pub fn decode_from_stream<S: Read + ?Sized>(
51 stream: &mut S,
52 is_open_secure_channel: bool,
53 decoding_options: &DecodingOptions,
54 ) -> EncodingResult<Self> {
55 if is_open_secure_channel {
56 let security_header = AsymmetricSecurityHeader::decode(stream, decoding_options)?;
57
58 let security_policy = if security_header.security_policy_uri.is_empty() {
59 SecurityPolicy::None
60 } else {
61 SecurityPolicy::from_uri(security_header.security_policy_uri.as_ref())
62 };
63
64 if security_policy == SecurityPolicy::Unknown {
65 return Err(Error::new(
66 StatusCode::BadSecurityPolicyRejected,
67 format!(
68 "Security policy of chunk is unknown, policy = {:?}",
69 security_header.security_policy_uri
70 ),
71 ));
72 }
73
74 Ok(SecurityHeader::Asymmetric(security_header))
75 } else {
76 let security_header = SymmetricSecurityHeader::decode(stream, decoding_options)?;
77 Ok(SecurityHeader::Symmetric(security_header))
78 }
79 }
80}
81
82#[derive(Debug, Clone, PartialEq)]
83pub struct SymmetricSecurityHeader {
85 pub token_id: u32,
87}
88
89impl SimpleBinaryEncodable for SymmetricSecurityHeader {
90 fn byte_len(&self) -> usize {
91 4
92 }
93
94 fn encode<S: Write + ?Sized>(&self, stream: &mut S) -> EncodingResult<()> {
95 self.token_id.encode(stream)
96 }
97}
98
99impl SimpleBinaryDecodable for SymmetricSecurityHeader {
100 fn decode<S: Read + ?Sized>(
101 stream: &mut S,
102 decoding_options: &DecodingOptions,
103 ) -> EncodingResult<Self> {
104 let token_id = u32::decode(stream, decoding_options)?;
105 Ok(SymmetricSecurityHeader { token_id })
106 }
107}
108
109#[derive(Debug, Clone, PartialEq)]
110pub struct AsymmetricSecurityHeader {
112 pub security_policy_uri: UAString,
114 pub sender_certificate: ByteString,
116 pub receiver_certificate_thumbprint: ByteString,
118}
119
120impl SimpleBinaryEncodable for AsymmetricSecurityHeader {
121 fn byte_len(&self) -> usize {
122 let mut size = 0;
123 size += self.security_policy_uri.byte_len();
124 size += self.sender_certificate.byte_len();
125 size += self.receiver_certificate_thumbprint.byte_len();
126 size
127 }
128
129 fn encode<S: Write + ?Sized>(&self, stream: &mut S) -> EncodingResult<()> {
130 self.security_policy_uri.encode(stream)?;
131 self.sender_certificate.encode(stream)?;
132 self.receiver_certificate_thumbprint.encode(stream)?;
133 Ok(())
134 }
135}
136
137impl SimpleBinaryDecodable for AsymmetricSecurityHeader {
138 fn decode<S: Read + ?Sized>(
139 stream: &mut S,
140 decoding_options: &DecodingOptions,
141 ) -> EncodingResult<Self> {
142 let security_policy_uri = UAString::decode(stream, decoding_options)?;
143 let sender_certificate = ByteString::decode(stream, decoding_options)?;
144 let receiver_certificate_thumbprint = ByteString::decode(stream, decoding_options)?;
145
146 if sender_certificate
148 .value
149 .as_ref()
150 .is_some_and(|v| v.len() >= constants::MAX_CERTIFICATE_LENGTH)
151 {
152 Err(Error::new(
153 StatusCode::BadEncodingLimitsExceeded,
154 format!(
155 "Sender certificate has length {}, which exceeds max certificate size {}",
156 sender_certificate
157 .value
158 .as_ref()
159 .map(|v| v.len())
160 .unwrap_or_default(),
161 constants::MAX_CERTIFICATE_LENGTH
162 ),
163 ))
164 } else {
165 let thumbprint_len = if let Some(value) = &receiver_certificate_thumbprint.value {
167 value.len()
168 } else {
169 0
170 };
171 if thumbprint_len > 0 && thumbprint_len != Thumbprint::THUMBPRINT_SIZE {
172 Err(Error::decoding(format!(
173 "Receiver certificate thumbprint is not 20 bytes long, {} bytes",
174 receiver_certificate_thumbprint
175 .value
176 .as_ref()
177 .unwrap()
178 .len(),
179 )))
180 } else {
181 Ok(AsymmetricSecurityHeader {
182 security_policy_uri,
183 sender_certificate,
184 receiver_certificate_thumbprint,
185 })
186 }
187 }
188 }
189}
190
191impl AsymmetricSecurityHeader {
192 pub fn none() -> AsymmetricSecurityHeader {
194 AsymmetricSecurityHeader {
195 security_policy_uri: UAString::from(SecurityPolicy::None.to_uri()),
196 sender_certificate: ByteString::null(),
197 receiver_certificate_thumbprint: ByteString::null(),
198 }
199 }
200
201 pub fn new(
203 security_policy: SecurityPolicy,
204 sender_certificate: &X509,
205 receiver_certificate_thumbprint: ByteString,
206 ) -> AsymmetricSecurityHeader {
207 AsymmetricSecurityHeader {
208 security_policy_uri: UAString::from(security_policy.to_uri()),
209 sender_certificate: sender_certificate.as_byte_string(),
210 receiver_certificate_thumbprint,
211 }
212 }
213}
214
215#[derive(Debug, Clone, PartialEq)]
216pub struct SequenceHeader {
219 pub sequence_number: u32,
221 pub request_id: u32,
223}
224
225impl SimpleBinaryEncodable for SequenceHeader {
226 fn byte_len(&self) -> usize {
227 8
228 }
229
230 fn encode<S: Write + ?Sized>(&self, stream: &mut S) -> EncodingResult<()> {
231 self.sequence_number.encode(stream)?;
232 self.request_id.encode(stream)?;
233 Ok(())
234 }
235}
236
237impl SimpleBinaryDecodable for SequenceHeader {
238 fn decode<S: Read + ?Sized>(
239 stream: &mut S,
240 decoding_options: &DecodingOptions,
241 ) -> EncodingResult<Self> {
242 let sequence_number = u32::decode(stream, decoding_options)?;
243 let request_id = u32::decode(stream, decoding_options)?;
244 Ok(SequenceHeader {
245 sequence_number,
246 request_id,
247 })
248 }
249}