1use serde::{Deserialize, Serialize};
7use thiserror::Error;
8use tracing::{debug, trace};
9
10use super::policy::SecurityPolicyConfig;
11use crate::config::SecurityPolicy;
12
13#[derive(Debug, Error)]
15pub enum CryptoError {
16 #[error("Encryption failed: {0}")]
17 EncryptionFailed(String),
18
19 #[error("Decryption failed: {0}")]
20 DecryptionFailed(String),
21
22 #[error("Signing failed: {0}")]
23 SigningFailed(String),
24
25 #[error("Verification failed: {0}")]
26 VerificationFailed(String),
27
28 #[error("Invalid key: {0}")]
29 InvalidKey(String),
30
31 #[error("Invalid data: {0}")]
32 InvalidData(String),
33
34 #[error("Unsupported algorithm: {0}")]
35 UnsupportedAlgorithm(String),
36
37 #[error("Key generation failed: {0}")]
38 KeyGenerationFailed(String),
39}
40
41pub type CryptoResult<T> = Result<T, CryptoError>;
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
46pub enum SymmetricAlgorithm {
47 None,
49 Aes128Cbc,
51 Aes256Cbc,
53}
54
55impl SymmetricAlgorithm {
56 pub fn key_length(&self) -> usize {
58 match self {
59 Self::None => 0,
60 Self::Aes128Cbc => 16,
61 Self::Aes256Cbc => 32,
62 }
63 }
64
65 pub fn block_size(&self) -> usize {
67 match self {
68 Self::None => 0,
69 Self::Aes128Cbc | Self::Aes256Cbc => 16,
70 }
71 }
72
73 pub fn iv_length(&self) -> usize {
75 self.block_size()
76 }
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
81pub enum AsymmetricAlgorithm {
82 None,
84 RsaPkcs1,
86 RsaOaepSha1,
88 RsaOaepSha256,
90 RsaPssSha256,
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
96pub enum HashAlgorithm {
97 Sha1,
99 Sha256,
101 Sha384,
103 Sha512,
105}
106
107impl HashAlgorithm {
108 pub fn output_length(&self) -> usize {
110 match self {
111 Self::Sha1 => 20,
112 Self::Sha256 => 32,
113 Self::Sha384 => 48,
114 Self::Sha512 => 64,
115 }
116 }
117}
118
119#[derive(Debug, Clone)]
121pub struct EncryptionResult {
122 pub ciphertext: Vec<u8>,
124 pub iv: Option<Vec<u8>>,
126}
127
128#[derive(Debug, Clone)]
130pub struct DecryptionResult {
131 pub plaintext: Vec<u8>,
133}
134
135#[derive(Debug, Clone)]
137pub struct SignatureResult {
138 pub signature: Vec<u8>,
140}
141
142#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct CryptoProviderConfig {
145 pub enable_hw_acceleration: bool,
147 pub rng_seed: Option<u64>,
149}
150
151impl Default for CryptoProviderConfig {
152 fn default() -> Self {
153 Self {
154 enable_hw_acceleration: true,
155 rng_seed: None,
156 }
157 }
158}
159
160#[derive(Debug, Clone)]
162pub struct KeyMaterial {
163 pub signing_key: Vec<u8>,
165 pub encrypting_key: Vec<u8>,
167 pub iv: Vec<u8>,
169}
170
171impl KeyMaterial {
172 pub fn empty() -> Self {
174 Self {
175 signing_key: Vec::new(),
176 encrypting_key: Vec::new(),
177 iv: Vec::new(),
178 }
179 }
180
181 pub fn is_valid_for(&self, policy: &SecurityPolicyConfig) -> bool {
183 if policy.policy == SecurityPolicy::None {
184 return true;
185 }
186
187 self.signing_key.len() >= policy.derived_signature_key_length as usize
188 && self.encrypting_key.len() >= policy.symmetric_key_length as usize
189 && self.iv.len() >= policy.symmetric_block_size as usize
190 }
191}
192
193pub struct CryptoProvider {
198 config: CryptoProviderConfig,
199 policy_config: SecurityPolicyConfig,
200}
201
202impl CryptoProvider {
203 pub fn new(policy: SecurityPolicy) -> Self {
205 Self {
206 config: CryptoProviderConfig::default(),
207 policy_config: SecurityPolicyConfig::for_policy(policy),
208 }
209 }
210
211 pub fn with_config(policy: SecurityPolicy, config: CryptoProviderConfig) -> Self {
213 Self {
214 config,
215 policy_config: SecurityPolicyConfig::for_policy(policy),
216 }
217 }
218
219 pub fn policy(&self) -> SecurityPolicy {
221 self.policy_config.policy
222 }
223
224 pub fn policy_config(&self) -> &SecurityPolicyConfig {
226 &self.policy_config
227 }
228
229 pub fn symmetric_encrypt(
235 &self,
236 plaintext: &[u8],
237 key: &[u8],
238 iv: &[u8],
239 ) -> CryptoResult<EncryptionResult> {
240 if self.policy_config.policy == SecurityPolicy::None {
241 return Ok(EncryptionResult {
242 ciphertext: plaintext.to_vec(),
243 iv: None,
244 });
245 }
246
247 let expected_key_len = self.policy_config.symmetric_key_length as usize;
249 let expected_iv_len = self.policy_config.symmetric_block_size as usize;
250
251 if key.len() != expected_key_len {
252 return Err(CryptoError::InvalidKey(format!(
253 "Expected key length {}, got {}",
254 expected_key_len,
255 key.len()
256 )));
257 }
258
259 if iv.len() != expected_iv_len {
260 return Err(CryptoError::InvalidData(format!(
261 "Expected IV length {}, got {}",
262 expected_iv_len,
263 iv.len()
264 )));
265 }
266
267 let block_size = self.policy_config.symmetric_block_size as usize;
269 let padded = pkcs7_pad(plaintext, block_size);
270
271 let ciphertext = simulate_aes_cbc_encrypt(&padded, key, iv);
274
275 trace!(
276 plaintext_len = plaintext.len(),
277 ciphertext_len = ciphertext.len(),
278 "Symmetric encryption completed"
279 );
280
281 Ok(EncryptionResult {
282 ciphertext,
283 iv: Some(iv.to_vec()),
284 })
285 }
286
287 pub fn symmetric_decrypt(
289 &self,
290 ciphertext: &[u8],
291 key: &[u8],
292 iv: &[u8],
293 ) -> CryptoResult<DecryptionResult> {
294 if self.policy_config.policy == SecurityPolicy::None {
295 return Ok(DecryptionResult {
296 plaintext: ciphertext.to_vec(),
297 });
298 }
299
300 let block_size = self.policy_config.symmetric_block_size as usize;
302 if ciphertext.len() % block_size != 0 {
303 return Err(CryptoError::InvalidData(
304 "Ciphertext length must be multiple of block size".to_string(),
305 ));
306 }
307
308 let decrypted = simulate_aes_cbc_decrypt(ciphertext, key, iv);
310
311 let plaintext = pkcs7_unpad(&decrypted).map_err(|e| CryptoError::DecryptionFailed(e))?;
313
314 trace!(
315 ciphertext_len = ciphertext.len(),
316 plaintext_len = plaintext.len(),
317 "Symmetric decryption completed"
318 );
319
320 Ok(DecryptionResult { plaintext })
321 }
322
323 pub fn asymmetric_encrypt(
329 &self,
330 plaintext: &[u8],
331 public_key: &[u8],
332 ) -> CryptoResult<EncryptionResult> {
333 if self.policy_config.policy == SecurityPolicy::None {
334 return Ok(EncryptionResult {
335 ciphertext: plaintext.to_vec(),
336 iv: None,
337 });
338 }
339
340 if public_key.is_empty() {
342 return Err(CryptoError::InvalidKey("Empty public key".to_string()));
343 }
344
345 let ciphertext = simulate_rsa_encrypt(plaintext, public_key);
348
349 debug!(
350 plaintext_len = plaintext.len(),
351 ciphertext_len = ciphertext.len(),
352 "Asymmetric encryption completed"
353 );
354
355 Ok(EncryptionResult {
356 ciphertext,
357 iv: None,
358 })
359 }
360
361 pub fn asymmetric_decrypt(
363 &self,
364 ciphertext: &[u8],
365 private_key: &[u8],
366 ) -> CryptoResult<DecryptionResult> {
367 if self.policy_config.policy == SecurityPolicy::None {
368 return Ok(DecryptionResult {
369 plaintext: ciphertext.to_vec(),
370 });
371 }
372
373 if private_key.is_empty() {
375 return Err(CryptoError::InvalidKey("Empty private key".to_string()));
376 }
377
378 let plaintext = simulate_rsa_decrypt(ciphertext, private_key);
380
381 debug!(
382 ciphertext_len = ciphertext.len(),
383 plaintext_len = plaintext.len(),
384 "Asymmetric decryption completed"
385 );
386
387 Ok(DecryptionResult { plaintext })
388 }
389
390 pub fn hmac_sign(&self, data: &[u8], key: &[u8]) -> CryptoResult<SignatureResult> {
396 if self.policy_config.policy == SecurityPolicy::None {
397 return Ok(SignatureResult {
398 signature: Vec::new(),
399 });
400 }
401
402 let signature = simulate_hmac_sha256(data, key);
404
405 trace!(
406 data_len = data.len(),
407 sig_len = signature.len(),
408 "HMAC sign completed"
409 );
410
411 Ok(SignatureResult { signature })
412 }
413
414 pub fn hmac_verify(&self, data: &[u8], key: &[u8], signature: &[u8]) -> CryptoResult<bool> {
416 if self.policy_config.policy == SecurityPolicy::None {
417 return Ok(true);
418 }
419
420 let expected = simulate_hmac_sha256(data, key);
421 let valid = constant_time_compare(&expected, signature);
422
423 trace!(valid, "HMAC verify completed");
424
425 Ok(valid)
426 }
427
428 pub fn rsa_sign(&self, data: &[u8], private_key: &[u8]) -> CryptoResult<SignatureResult> {
430 if self.policy_config.policy == SecurityPolicy::None {
431 return Ok(SignatureResult {
432 signature: Vec::new(),
433 });
434 }
435
436 let signature = simulate_rsa_sign(data, private_key);
438
439 debug!(
440 data_len = data.len(),
441 sig_len = signature.len(),
442 "RSA sign completed"
443 );
444
445 Ok(SignatureResult { signature })
446 }
447
448 pub fn rsa_verify(
450 &self,
451 data: &[u8],
452 public_key: &[u8],
453 signature: &[u8],
454 ) -> CryptoResult<bool> {
455 if self.policy_config.policy == SecurityPolicy::None {
456 return Ok(true);
457 }
458
459 let valid = simulate_rsa_verify(data, public_key, signature);
461
462 debug!(valid, "RSA verify completed");
463
464 Ok(valid)
465 }
466
467 pub fn hash(&self, algorithm: HashAlgorithm, data: &[u8]) -> Vec<u8> {
473 match algorithm {
474 HashAlgorithm::Sha1 => simulate_sha1(data),
475 HashAlgorithm::Sha256 => simulate_sha256(data),
476 HashAlgorithm::Sha384 => simulate_sha384(data),
477 HashAlgorithm::Sha512 => simulate_sha512(data),
478 }
479 }
480
481 pub fn sha256(&self, data: &[u8]) -> Vec<u8> {
483 self.hash(HashAlgorithm::Sha256, data)
484 }
485
486 pub fn derive_keys(
492 &self,
493 secret: &[u8],
494 seed: &[u8],
495 signing_key_length: usize,
496 encrypting_key_length: usize,
497 iv_length: usize,
498 ) -> CryptoResult<KeyMaterial> {
499 if self.policy_config.policy == SecurityPolicy::None {
500 return Ok(KeyMaterial::empty());
501 }
502
503 let total_length = signing_key_length + encrypting_key_length + iv_length;
505 let derived = p_sha256(secret, seed, total_length);
506
507 let signing_key = derived[..signing_key_length].to_vec();
508 let encrypting_key =
509 derived[signing_key_length..signing_key_length + encrypting_key_length].to_vec();
510 let iv = derived[signing_key_length + encrypting_key_length..].to_vec();
511
512 debug!(
513 signing_key_len = signing_key.len(),
514 encrypting_key_len = encrypting_key.len(),
515 iv_len = iv.len(),
516 "Key derivation completed"
517 );
518
519 Ok(KeyMaterial {
520 signing_key,
521 encrypting_key,
522 iv,
523 })
524 }
525
526 pub fn random_bytes(&self, length: usize) -> Vec<u8> {
532 if let Some(seed) = self.config.rng_seed {
533 deterministic_random(seed, length)
535 } else {
536 secure_random(length)
538 }
539 }
540
541 pub fn generate_nonce(&self) -> Vec<u8> {
543 self.random_bytes(self.policy_config.secure_channel_nonce_length as usize)
544 }
545}
546
547fn pkcs7_pad(data: &[u8], block_size: usize) -> Vec<u8> {
553 let padding_len = block_size - (data.len() % block_size);
554 let mut padded = data.to_vec();
555 padded.extend(std::iter::repeat(padding_len as u8).take(padding_len));
556 padded
557}
558
559fn pkcs7_unpad(data: &[u8]) -> Result<Vec<u8>, String> {
561 if data.is_empty() {
562 return Err("Empty data".to_string());
563 }
564
565 let padding_len = *data.last().unwrap() as usize;
566 if padding_len == 0 || padding_len > data.len() || padding_len > 16 {
567 return Err("Invalid padding".to_string());
568 }
569
570 for &byte in &data[data.len() - padding_len..] {
572 if byte != padding_len as u8 {
573 return Err("Invalid padding bytes".to_string());
574 }
575 }
576
577 Ok(data[..data.len() - padding_len].to_vec())
578}
579
580fn constant_time_compare(a: &[u8], b: &[u8]) -> bool {
582 if a.len() != b.len() {
583 return false;
584 }
585
586 let mut result = 0u8;
587 for (x, y) in a.iter().zip(b.iter()) {
588 result |= x ^ y;
589 }
590 result == 0
591}
592
593fn simulate_aes_cbc_encrypt(plaintext: &[u8], key: &[u8], iv: &[u8]) -> Vec<u8> {
599 let mut ciphertext = Vec::with_capacity(plaintext.len());
601 let block_size = 16;
602
603 let mut prev_block = iv.to_vec();
604 for chunk in plaintext.chunks(block_size) {
605 let mut block = vec![0u8; block_size];
606 for (i, &byte) in chunk.iter().enumerate() {
607 block[i] = byte ^ prev_block[i] ^ key[i % key.len()];
608 }
609 prev_block = block.clone();
610 ciphertext.extend(block);
611 }
612
613 ciphertext
614}
615
616fn simulate_aes_cbc_decrypt(ciphertext: &[u8], key: &[u8], iv: &[u8]) -> Vec<u8> {
618 let mut plaintext = Vec::with_capacity(ciphertext.len());
619 let block_size = 16;
620
621 let mut prev_block = iv.to_vec();
622 for chunk in ciphertext.chunks(block_size) {
623 let mut block = vec![0u8; block_size];
624 for (i, &byte) in chunk.iter().enumerate() {
625 block[i] = byte ^ prev_block[i] ^ key[i % key.len()];
626 }
627 prev_block = chunk.to_vec();
628 plaintext.extend(block);
629 }
630
631 plaintext
632}
633
634fn simulate_rsa_encrypt(plaintext: &[u8], public_key: &[u8]) -> Vec<u8> {
636 plaintext
638 .iter()
639 .enumerate()
640 .map(|(i, &b)| b ^ public_key[i % public_key.len()])
641 .collect()
642}
643
644fn simulate_rsa_decrypt(ciphertext: &[u8], private_key: &[u8]) -> Vec<u8> {
646 ciphertext
648 .iter()
649 .enumerate()
650 .map(|(i, &b)| b ^ private_key[i % private_key.len()])
651 .collect()
652}
653
654fn simulate_hmac_sha256(data: &[u8], key: &[u8]) -> Vec<u8> {
656 let mut hash = vec![0u8; 32];
658 for (i, &b) in data.iter().enumerate() {
659 hash[i % 32] ^= b ^ key[i % key.len()];
660 }
661 hash
662}
663
664fn simulate_rsa_sign(data: &[u8], private_key: &[u8]) -> Vec<u8> {
666 simulate_hmac_sha256(data, private_key)
667}
668
669fn simulate_rsa_verify(data: &[u8], public_key: &[u8], signature: &[u8]) -> bool {
671 let expected = simulate_hmac_sha256(data, public_key);
672 constant_time_compare(&expected, signature)
673}
674
675fn simulate_sha1(data: &[u8]) -> Vec<u8> {
677 let mut hash = vec![0u8; 20];
678 for (i, &b) in data.iter().enumerate() {
679 hash[i % 20] = hash[i % 20].wrapping_add(b);
680 }
681 hash
682}
683
684fn simulate_sha256(data: &[u8]) -> Vec<u8> {
686 let mut hash = vec![0u8; 32];
687 for (i, &b) in data.iter().enumerate() {
688 hash[i % 32] = hash[i % 32].wrapping_add(b);
689 }
690 hash
691}
692
693fn simulate_sha384(data: &[u8]) -> Vec<u8> {
695 let mut hash = vec![0u8; 48];
696 for (i, &b) in data.iter().enumerate() {
697 hash[i % 48] = hash[i % 48].wrapping_add(b);
698 }
699 hash
700}
701
702fn simulate_sha512(data: &[u8]) -> Vec<u8> {
704 let mut hash = vec![0u8; 64];
705 for (i, &b) in data.iter().enumerate() {
706 hash[i % 64] = hash[i % 64].wrapping_add(b);
707 }
708 hash
709}
710
711fn p_sha256(secret: &[u8], seed: &[u8], length: usize) -> Vec<u8> {
713 let mut result = Vec::with_capacity(length);
714 let mut a = seed.to_vec();
715
716 while result.len() < length {
717 a = simulate_hmac_sha256(&a, secret);
718 let mut combined = a.clone();
719 combined.extend_from_slice(seed);
720 let p = simulate_hmac_sha256(&combined, secret);
721 result.extend(p);
722 }
723
724 result.truncate(length);
725 result
726}
727
728fn deterministic_random(seed: u64, length: usize) -> Vec<u8> {
730 let mut bytes = Vec::with_capacity(length);
731 let mut state = seed;
732
733 for _ in 0..length {
734 state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
735 bytes.push((state >> 56) as u8);
736 }
737
738 bytes
739}
740
741fn secure_random(length: usize) -> Vec<u8> {
743 use std::time::{SystemTime, UNIX_EPOCH};
744
745 let seed = SystemTime::now()
746 .duration_since(UNIX_EPOCH)
747 .unwrap()
748 .as_nanos() as u64;
749
750 deterministic_random(seed, length)
751}
752
753#[cfg(test)]
754mod tests {
755 use super::*;
756
757 #[test]
758 fn test_pkcs7_padding() {
759 let data = b"hello";
760 let padded = pkcs7_pad(data, 16);
761 assert_eq!(padded.len(), 16);
762 assert_eq!(padded[5..], [11u8; 11]);
763
764 let unpadded = pkcs7_unpad(&padded).unwrap();
765 assert_eq!(unpadded, data);
766 }
767
768 #[test]
769 fn test_symmetric_encrypt_decrypt() {
770 let provider = CryptoProvider::new(SecurityPolicy::Basic256Sha256);
771 let key = vec![0u8; 32];
772 let iv = vec![0u8; 16];
773 let plaintext = b"Hello, OPC UA!";
774
775 let encrypted = provider.symmetric_encrypt(plaintext, &key, &iv).unwrap();
776 let decrypted = provider
777 .symmetric_decrypt(&encrypted.ciphertext, &key, &iv)
778 .unwrap();
779
780 assert_eq!(decrypted.plaintext, plaintext);
781 }
782
783 #[test]
784 fn test_none_policy_passthrough() {
785 let provider = CryptoProvider::new(SecurityPolicy::None);
786 let data = b"test data";
787 let key = vec![0u8; 32];
788 let iv = vec![0u8; 16];
789
790 let encrypted = provider.symmetric_encrypt(data, &key, &iv).unwrap();
791 assert_eq!(encrypted.ciphertext, data);
792
793 let decrypted = provider.symmetric_decrypt(data, &key, &iv).unwrap();
794 assert_eq!(decrypted.plaintext, data);
795 }
796
797 #[test]
798 fn test_hmac_sign_verify() {
799 let provider = CryptoProvider::new(SecurityPolicy::Basic256Sha256);
800 let key = vec![0xAB; 32];
801 let data = b"Message to sign";
802
803 let signature = provider.hmac_sign(data, &key).unwrap();
804 let valid = provider
805 .hmac_verify(data, &key, &signature.signature)
806 .unwrap();
807
808 assert!(valid);
809 }
810
811 #[test]
812 fn test_key_derivation() {
813 let provider = CryptoProvider::new(SecurityPolicy::Basic256Sha256);
814 let secret = vec![0x42; 32];
815 let seed = vec![0x13; 32];
816
817 let keys = provider.derive_keys(&secret, &seed, 32, 32, 16).unwrap();
818
819 assert_eq!(keys.signing_key.len(), 32);
820 assert_eq!(keys.encrypting_key.len(), 32);
821 assert_eq!(keys.iv.len(), 16);
822 }
823
824 #[test]
825 fn test_nonce_generation() {
826 let provider = CryptoProvider::new(SecurityPolicy::Basic256Sha256);
827 let nonce = provider.generate_nonce();
828
829 assert_eq!(nonce.len(), 32);
830 }
831
832 #[test]
833 fn test_constant_time_compare() {
834 assert!(constant_time_compare(b"test", b"test"));
835 assert!(!constant_time_compare(b"test", b"Test"));
836 assert!(!constant_time_compare(b"test", b"testing"));
837 }
838}