Skip to main content

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