Skip to main content

opcua_crypto/policy/
mod.rs

1use opcua_types::{constants, Error, StatusCode};
2
3pub(crate) mod aes;
4
5pub use aes::AesDerivedKeys;
6pub(crate) use aes::AesPolicy;
7
8use crate::{PrivateKey, PublicKey};
9
10/// Information about padding given by the policy.
11pub struct PaddingInfo {
12    /// Plain text block size.
13    pub block_size: usize,
14    /// Minimum padding length.
15    pub minimum_padding: usize,
16}
17
18/// OPC-UA requires extra padding if the key size is > 2048 bits.
19fn minimum_padding(size: usize) -> usize {
20    if size <= 256 {
21        1
22    } else {
23        2
24    }
25}
26
27pub(crate) trait SecurityPolicyImpl {
28    /// The type of private key used by this security policy.
29    type TPrivateKey;
30    /// The type of public key used by this security policy.
31    type TPublicKey;
32    /// The type of derived key used by this security policy.
33    type TDerivedKey;
34
35    /// The OPC-UA security policy URI for this policy.
36    fn uri() -> &'static str;
37
38    /// Whether this security policy is deprecated.
39    fn is_deprecated() -> bool;
40
41    /// Get the OPC-UA string for this policy.
42    fn as_str() -> &'static str;
43
44    /// Get the symmetric signature size in bytes.
45    fn symmetric_signature_size() -> usize;
46
47    /// Calculate the cipher text size using the given plain text size and key.
48    fn calculate_cipher_text_size(plain_text_size: usize, key: &Self::TPublicKey) -> usize;
49
50    /// Get a string representation of the asymmetric signature algorithm used by this policy.
51    fn asymmetric_signature_algorithm() -> &'static str;
52
53    /// Get a string representation of the asymmetric encryption algorithm used by this policy.
54    fn asymmetric_encryption_algorithm() -> Option<&'static str>;
55
56    /// Whether this policy uses legacy sequence numbers.
57    fn uses_legacy_sequence_numbers() -> bool;
58
59    /// Get the plain text block size used by this policy.
60    fn plain_text_block_size() -> usize;
61
62    /// Get the secure channel nonce length used by this policy.
63    fn nonce_length() -> usize;
64
65    fn symmetric_padding_info() -> PaddingInfo;
66
67    fn asymmetric_padding_info(remote_key: &Self::TPublicKey) -> PaddingInfo;
68
69    /// Sign the data in `src` using `key`, writing the output to `signature`.
70    fn asymmetric_sign(
71        key: &Self::TPrivateKey,
72        src: &[u8],
73        signature: &mut [u8],
74    ) -> Result<usize, Error>;
75
76    /// Verify that the data in `src` was signed using the private key for `key`.
77    fn asymmetric_verify_signature(
78        key: &Self::TPublicKey,
79        src: &[u8],
80        signature: &[u8],
81    ) -> Result<(), Error>;
82
83    /// Asymetrically encrypt the data in `src` using `key`, writing the
84    /// result to `dst`.
85    fn asymmetric_encrypt(
86        key: &Self::TPublicKey,
87        src: &[u8],
88        dst: &mut [u8],
89    ) -> Result<usize, Error>;
90
91    /// Asymetrically decrypt the data in `src` using `key`, writing the
92    /// result to `dst`.
93    fn asymmetric_decrypt(
94        key: &Self::TPrivateKey,
95        src: &[u8],
96        dst: &mut [u8],
97    ) -> Result<usize, Error>;
98
99    // This will definitely need to change for ECC...
100    /// Produce the derived keys for this policy.
101    fn derive_secure_channel_keys(secret: &[u8], seed: &[u8]) -> Self::TDerivedKey;
102
103    /// Sign the data in `data` using the signing key in `keys`, writing the result to
104    /// `signature`.
105    fn symmetric_sign(
106        keys: &Self::TDerivedKey,
107        data: &[u8],
108        signature: &mut [u8],
109    ) -> Result<(), Error>;
110
111    /// Verify that the data in `data` was signed using `keys`.
112    fn symmetric_verify_signature(
113        keys: &Self::TDerivedKey,
114        data: &[u8],
115        signature: &[u8],
116    ) -> Result<(), Error>;
117
118    /// Encrypt the data in `src` using `keys`, writing the result to `dst`.
119    fn symmetric_encrypt(
120        keys: &Self::TDerivedKey,
121        src: &[u8],
122        dst: &mut [u8],
123    ) -> Result<usize, Error>;
124
125    /// Decrypt the data in `src` using `keys`, writing the result to `dst`.
126    fn symmetric_decrypt(
127        keys: &Self::TDerivedKey,
128        src: &[u8],
129        dst: &mut [u8],
130    ) -> Result<usize, Error>;
131
132    /// Get the length of the symmetric encryption key, in bytes.
133    fn encrypting_key_length() -> usize;
134
135    /// Validate that the given key length is valid.
136    fn is_valid_key_length(length: usize) -> bool;
137}
138
139/// The OPC-UA None policy, with a stub implementation of `SecurityPolicyImpl`.
140pub(crate) struct NonePolicy(());
141
142impl SecurityPolicyImpl for NonePolicy {
143    // Temp: In the future we'll want to be generic over this in the
144    // secure channel state, which means we could use a zero-sized type here.
145    type TPrivateKey = PrivateKey;
146    type TPublicKey = PublicKey;
147    type TDerivedKey = AesDerivedKeys;
148
149    fn uri() -> &'static str {
150        constants::SECURITY_POLICY_NONE_URI
151    }
152
153    fn is_deprecated() -> bool {
154        false
155    }
156
157    fn as_str() -> &'static str {
158        constants::SECURITY_POLICY_NONE
159    }
160
161    fn asymmetric_encryption_algorithm() -> Option<&'static str> {
162        None
163    }
164
165    fn asymmetric_signature_algorithm() -> &'static str {
166        constants::SECURITY_POLICY_NONE
167    }
168
169    fn symmetric_signature_size() -> usize {
170        0
171    }
172
173    fn uses_legacy_sequence_numbers() -> bool {
174        true
175    }
176
177    fn nonce_length() -> usize {
178        32
179    }
180
181    fn plain_text_block_size() -> usize {
182        // Not really valid, but strictly speaking the block size for None
183        // is 1, since there's no blocks at all.
184        1
185    }
186
187    fn asymmetric_padding_info(_remote_key: &Self::TPublicKey) -> PaddingInfo {
188        PaddingInfo {
189            block_size: 0,
190            minimum_padding: 0,
191        }
192    }
193
194    fn symmetric_padding_info() -> PaddingInfo {
195        PaddingInfo {
196            block_size: 0,
197            minimum_padding: 0,
198        }
199    }
200
201    fn is_valid_key_length(_length: usize) -> bool {
202        // Should we do something else here? I don't think we care.
203        true
204    }
205
206    fn calculate_cipher_text_size(_plain_text_size: usize, _key: &Self::TPublicKey) -> usize {
207        panic!("Cannot encrypt using security policy None")
208    }
209
210    fn asymmetric_sign(
211        _key: &Self::TPrivateKey,
212        _data: &[u8],
213        _out: &mut [u8],
214    ) -> Result<usize, Error> {
215        Err(Error::new(
216            StatusCode::BadInternalError,
217            "Cannot sign using security policy None",
218        ))
219    }
220
221    fn asymmetric_verify_signature(
222        _key: &Self::TPublicKey,
223        _data: &[u8],
224        _signature: &[u8],
225    ) -> Result<(), Error> {
226        Err(Error::new(
227            StatusCode::BadInternalError,
228            "Cannot verify signature using security policy None",
229        ))
230    }
231
232    fn asymmetric_encrypt(
233        _key: &Self::TPublicKey,
234        _data: &[u8],
235        _out: &mut [u8],
236    ) -> Result<usize, Error> {
237        Err(Error::new(
238            StatusCode::BadInternalError,
239            "Cannot encrypt using security policy None",
240        ))
241    }
242
243    fn asymmetric_decrypt(
244        _key: &Self::TPrivateKey,
245        _src: &[u8],
246        _dst: &mut [u8],
247    ) -> Result<usize, Error> {
248        Err(Error::new(
249            StatusCode::BadInternalError,
250            "Cannot decrypt using security policy None",
251        ))
252    }
253
254    fn derive_secure_channel_keys(_secret: &[u8], _seed: &[u8]) -> Self::TDerivedKey {
255        panic!("Cannot derive encryption keys for security policy None")
256    }
257
258    fn symmetric_decrypt(
259        _keys: &Self::TDerivedKey,
260        _src: &[u8],
261        _dst: &mut [u8],
262    ) -> Result<usize, Error> {
263        Err(Error::new(
264            StatusCode::BadInternalError,
265            "Cannot decrypt using security policy None",
266        ))
267    }
268
269    fn symmetric_encrypt(
270        _keys: &Self::TDerivedKey,
271        _src: &[u8],
272        _dst: &mut [u8],
273    ) -> Result<usize, Error> {
274        Err(Error::new(
275            StatusCode::BadInternalError,
276            "Cannot encrypt using security policy None",
277        ))
278    }
279
280    fn symmetric_sign(
281        _keys: &Self::TDerivedKey,
282        _data: &[u8],
283        _signature: &mut [u8],
284    ) -> Result<(), Error> {
285        Err(Error::new(
286            StatusCode::BadInternalError,
287            "Cannot sign using security policy None",
288        ))
289    }
290
291    fn symmetric_verify_signature(
292        _keys: &Self::TDerivedKey,
293        _data: &[u8],
294        _signature: &[u8],
295    ) -> Result<(), Error> {
296        Err(Error::new(
297            StatusCode::BadInternalError,
298            "Cannot verify signature using security policy None",
299        ))
300    }
301
302    fn encrypting_key_length() -> usize {
303        0
304    }
305}