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