opcua_core/comms/
security_header.rs

1// OPCUA for Rust
2// SPDX-License-Identifier: MPL-2.0
3// Copyright (C) 2017-2022 Adam Lock
4
5use std::io::{Read, Write};
6
7use opcua_types::constants;
8use opcua_types::status_code::StatusCode;
9use opcua_types::*;
10
11use opcua_crypto::{SecurityPolicy, Thumbprint, X509};
12
13/// Holds the security header associated with the chunk. Secure channel requests use an asymmetric
14/// security header, regular messages use a symmetric security header.
15#[derive(Debug, Clone, PartialEq)]
16pub enum SecurityHeader {
17    Asymmetric(AsymmetricSecurityHeader),
18    Symmetric(SymmetricSecurityHeader),
19}
20
21impl BinaryEncoder<SecurityHeader> for SecurityHeader {
22    fn byte_len(&self) -> usize {
23        match self {
24            SecurityHeader::Asymmetric(value) => value.byte_len(),
25            SecurityHeader::Symmetric(value) => value.byte_len(),
26        }
27    }
28
29    fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
30        match self {
31            SecurityHeader::Asymmetric(value) => value.encode(stream),
32            SecurityHeader::Symmetric(value) => value.encode(stream),
33        }
34    }
35
36    fn decode<S: Read>(_: &mut S, _: &DecodingOptions) -> EncodingResult<Self> {
37        unimplemented!();
38    }
39}
40
41#[derive(Debug, Clone, PartialEq)]
42pub struct SymmetricSecurityHeader {
43    pub token_id: u32,
44}
45
46impl BinaryEncoder<SymmetricSecurityHeader> for SymmetricSecurityHeader {
47    fn byte_len(&self) -> usize {
48        4
49    }
50
51    fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
52        self.token_id.encode(stream)
53    }
54
55    fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
56        let token_id = u32::decode(stream, decoding_options)?;
57        Ok(SymmetricSecurityHeader { token_id })
58    }
59}
60
61#[derive(Debug, Clone, PartialEq)]
62pub struct AsymmetricSecurityHeader {
63    pub security_policy_uri: UAString,
64    pub sender_certificate: ByteString,
65    pub receiver_certificate_thumbprint: ByteString,
66}
67
68impl BinaryEncoder<AsymmetricSecurityHeader> for AsymmetricSecurityHeader {
69    fn byte_len(&self) -> usize {
70        let mut size = 0;
71        size += self.security_policy_uri.byte_len();
72        size += self.sender_certificate.byte_len();
73        size += self.receiver_certificate_thumbprint.byte_len();
74        size
75    }
76
77    fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
78        let mut size = 0;
79        size += self.security_policy_uri.encode(stream)?;
80        size += self.sender_certificate.encode(stream)?;
81        size += self.receiver_certificate_thumbprint.encode(stream)?;
82        assert_eq!(size, self.byte_len());
83        Ok(size)
84    }
85
86    fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
87        let security_policy_uri = UAString::decode(stream, decoding_options)?;
88        let sender_certificate = ByteString::decode(stream, decoding_options)?;
89        let receiver_certificate_thumbprint = ByteString::decode(stream, decoding_options)?;
90
91        // validate sender_certificate_length < MaxCertificateSize
92        if sender_certificate.value.is_some()
93            && sender_certificate.value.as_ref().unwrap().len()
94                >= constants::MAX_CERTIFICATE_LENGTH as usize
95        {
96            error!("Sender certificate exceeds max certificate size");
97            Err(StatusCode::BadDecodingError)
98        } else {
99            // validate receiver_certificate_thumbprint_length == 20
100            let thumbprint_len = if receiver_certificate_thumbprint.value.is_some() {
101                receiver_certificate_thumbprint
102                    .value
103                    .as_ref()
104                    .unwrap()
105                    .len()
106            } else {
107                0
108            };
109            if thumbprint_len > 0 && thumbprint_len != Thumbprint::THUMBPRINT_SIZE {
110                error!(
111                    "Receiver certificate thumbprint is not 20 bytes long, {} bytes",
112                    receiver_certificate_thumbprint
113                        .value
114                        .as_ref()
115                        .unwrap()
116                        .len()
117                );
118                Err(StatusCode::BadDecodingError)
119            } else {
120                Ok(AsymmetricSecurityHeader {
121                    security_policy_uri,
122                    sender_certificate,
123                    receiver_certificate_thumbprint,
124                })
125            }
126        }
127    }
128}
129
130impl AsymmetricSecurityHeader {
131    pub fn none() -> AsymmetricSecurityHeader {
132        AsymmetricSecurityHeader {
133            security_policy_uri: UAString::from(SecurityPolicy::None.to_uri()),
134            sender_certificate: ByteString::null(),
135            receiver_certificate_thumbprint: ByteString::null(),
136        }
137    }
138
139    pub fn new(
140        security_policy: SecurityPolicy,
141        sender_certificate: &X509,
142        receiver_certificate_thumbprint: ByteString,
143    ) -> AsymmetricSecurityHeader {
144        AsymmetricSecurityHeader {
145            security_policy_uri: UAString::from(security_policy.to_uri()),
146            sender_certificate: sender_certificate.as_byte_string(),
147            receiver_certificate_thumbprint,
148        }
149    }
150}
151
152#[derive(Debug, Clone, PartialEq)]
153pub struct SequenceHeader {
154    pub sequence_number: u32,
155    pub request_id: u32,
156}
157
158impl BinaryEncoder<SequenceHeader> for SequenceHeader {
159    fn byte_len(&self) -> usize {
160        8
161    }
162
163    fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
164        let mut size: usize = 0;
165        size += self.sequence_number.encode(stream)?;
166        size += self.request_id.encode(stream)?;
167        Ok(size)
168    }
169
170    fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
171        let sequence_number = u32::decode(stream, decoding_options)?;
172        let request_id = u32::decode(stream, decoding_options)?;
173        Ok(SequenceHeader {
174            sequence_number,
175            request_id,
176        })
177    }
178}