1use std::{
2 fmt, io,
3 net::{ToSocketAddrs, UdpSocket},
4 str::FromStr,
5};
6
7use rand::RngCore;
8
9use aes::Aes256;
10use aws_lc_rs::{aead::{
11 nonce_sequence, Aad, BoundKey, OpeningKey, SealingKey, UnboundKey, AES_128_GCM, AES_256_GCM
12}, error};
13use bincode::Options;
14use bitfield::bitfield;
15use clap::ValueEnum;
16use derive_builder::Builder;
17use etherparse::{
18 ether_type, ip_number, Ethernet2Header, IpHeader, Ipv4Header, Ipv6Header, PacketHeaders,
19 SerializedSize, TransportHeader, UdpHeader,
20};
21use log::debug;
22use pnet_packet::Packet;
23
24use serde::{Deserialize, Serialize};
25
26mod packet;
27use packet::psp::PspPacket;
28
29pub const PSP_ICV_SIZE: usize = 16;
30const PSP_VC_SIZE: usize = 8;
31const PSP_MASTER_KEY_SIZE: usize = 32;
32const PSP_SPI_KEY_SELECTOR_BIT: u32 = 31;
33const PSP_CRYPT_OFFSET_UNITS: usize = 4;
34const PSP_UDP_PORT: u16 = 1000;
35const PSP_HDR_FIXED_LEN: u8 = 16;
36
37#[repr(u8)]
39#[derive(Debug, PartialEq)]
40enum PspVersion {
41 PspVer0 = 0, PspVer1 = 1, }
44
45impl TryFrom<u8> for PspVersion {
46 type Error = PspError;
47
48 fn try_from(value: u8) -> Result<Self, Self::Error> {
49 match value {
50 0 => Ok(PspVersion::PspVer0),
51 1 => Ok(PspVersion::PspVer1),
52 _ => Err(PspError::InvalidPspVersion(value)),
53 }
54 }
55}
56
57#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, clap::ValueEnum)]
59pub enum PspEncap {
60 #[default]
61 Transport,
62 Tunnel,
63}
64
65impl fmt::Display for PspEncap {
66 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67 match self {
68 Self::Transport => write!(f, "transport"),
69 Self::Tunnel => write!(f, "tunnel"),
70 }
71 }
72}
73
74impl FromStr for PspEncap {
75 type Err = PspError;
76
77 fn from_str(s: &str) -> Result<PspEncap, Self::Err> {
78 match s {
79 "transport" => Ok(PspEncap::Transport),
80 "tunnel" => Ok(PspEncap::Tunnel),
81 _ => Err(PspError::InvalidPspEncap(s.to_string())),
82 }
83 }
84}
85
86#[derive(PartialEq, Eq, Copy, Clone, Debug, Default, Serialize, Deserialize, ValueEnum)]
88pub enum CryptoAlg {
89 AesGcm128,
90 #[default]
91 AesGcm256,
92}
93
94impl fmt::Display for CryptoAlg {
95 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96 match self {
97 Self::AesGcm128 => write!(f, "aes-gcm-128"),
98 Self::AesGcm256 => write!(f, "aes-gcm-256"),
99 }
100 }
101}
102
103impl FromStr for CryptoAlg {
104 type Err = PspError;
105
106 fn from_str(s: &str) -> Result<CryptoAlg, Self::Err> {
107 match s {
108 "aes-gcm-128" => Ok(CryptoAlg::AesGcm128),
109 "aes-gcm-256" => Ok(CryptoAlg::AesGcm256),
110 _ => Err(PspError::InvalidCryptoAlg(s.to_string())),
111 }
112 }
113}
114
115bitfield! {
117 #[derive(Copy, Clone, Serialize, PartialEq, Eq)]
118 pub struct PspHeaderFlags(u8);
119 impl Debug;
120 r, set_r: 0;
121 v, set_v: 1;
122 version, set_version: 5, 2;
123 d, set_d: 6;
124 s, set_s: 7;
125}
126
127impl Default for PspHeaderFlags {
128 fn default() -> Self {
129 let mut flags = Self(0);
130 flags.set_r(true);
131 flags.set_v(false);
132 flags.set_version(PspVersion::PspVer0 as u8);
133 flags.set_d(false);
134 flags.set_s(false);
135 flags
136 }
137}
138
139#[derive(Builder, Serialize, Debug, Default)]
140#[builder(default)]
141pub struct PspHeader {
142 next_hdr: u8,
149 hdr_ext_len: u8,
150 crypt_off: u8,
151 flags: PspHeaderFlags,
152 spi: u32,
153 iv: u64,
154}
155
156pub type PspMasterKey = [u8; PSP_MASTER_KEY_SIZE];
157
158type PspDerivedKey = Vec<u8>;
159
160#[derive(Clone, Debug, Default, Serialize, Deserialize)]
162pub struct PspConfig {
163 pub master_keys: [PspMasterKey; 2],
164 pub spi: u32,
165 pub psp_encap: PspEncap,
166 pub crypto_alg: CryptoAlg,
167 pub transport_crypt_off: u8,
168 pub ipv4_tunnel_crypt_off: u8,
169 pub ipv6_tunnel_crypt_off: u8,
170 pub include_vc: bool,
171}
172
173impl PspConfig {
174 pub fn validate(&self) -> Result<(), PspError> {
176 if self.spi == 0 {
178 return Err(PspError::InvalidSpi(self.spi));
179 }
180
181 for (i, key) in self.master_keys.iter().enumerate() {
183 if key.iter().all(|&b| b == 0) {
184 return Err(PspError::WeakKey(format!("Master key {} is all zeros", i)));
185 }
186
187 let first_byte = key[0];
189 if key.iter().all(|&b| b == first_byte) {
190 return Err(PspError::WeakKey(format!(
191 "Master key {} uses repeating pattern (0x{:02X})", i, first_byte
192 )));
193 }
194 }
195
196 if self.transport_crypt_off > 64 {
198 return Err(PspError::ConfigError(format!(
199 "Transport crypto offset too large: {}", self.transport_crypt_off
200 )));
201 }
202
203 if self.ipv4_tunnel_crypt_off > 64 {
204 return Err(PspError::ConfigError(format!(
205 "IPv4 tunnel crypto offset too large: {}", self.ipv4_tunnel_crypt_off
206 )));
207 }
208
209 if self.ipv6_tunnel_crypt_off > 64 {
210 return Err(PspError::ConfigError(format!(
211 "IPv6 tunnel crypto offset too large: {}", self.ipv6_tunnel_crypt_off
212 )));
213 }
214
215 Ok(())
216 }
217
218 pub fn secure_clear(&mut self) {
222 for key in &mut self.master_keys {
224 for byte in key.iter_mut() {
225 unsafe {
226 std::ptr::write_volatile(byte, 0);
227 }
228 }
229 }
230
231 unsafe {
233 std::ptr::write_volatile(&mut self.spi, 0);
234 }
235 }
236
237 pub fn new_secure() -> Result<Self, PspError> {
239 let cfg = PspConfig {
240 master_keys: [
241 PktContext::generate_secure_key(),
242 PktContext::generate_secure_key(),
243 ],
244 spi: PktContext::generate_secure_spi(),
245 psp_encap: PspEncap::Transport,
246 crypto_alg: CryptoAlg::AesGcm256, transport_crypt_off: 0,
248 ipv4_tunnel_crypt_off: 0,
249 ipv6_tunnel_crypt_off: 0,
250 include_vc: false,
251 };
252
253 cfg.validate()?;
254 Ok(cfg)
255 }
256}
257
258#[derive(Debug, Clone)]
259pub struct PktContext {
260 pub psp_cfg: PspConfig,
261 pub key: PspDerivedKey,
262 pub iv: u64,
263 pub vc: u64,
264}
265
266impl PktContext {
267 pub fn new() -> PktContext {
271 PktContext {
272 psp_cfg: PspConfig {
273 master_keys: [
274 Self::generate_secure_key(),
275 Self::generate_secure_key(),
276 ],
277 spi: Self::generate_secure_spi(),
278 psp_encap: PspEncap::Transport,
279 crypto_alg: CryptoAlg::AesGcm128,
280 transport_crypt_off: 0,
281 ipv4_tunnel_crypt_off: 0,
282 ipv6_tunnel_crypt_off: 0,
283 include_vc: false,
284 },
285 key: Self::generate_derived_key(16),
286 iv: Self::generate_secure_iv(),
287 vc: 0,
288 }
289 }
290
291 pub fn generate_secure_key() -> [u8; 32] {
293 let mut key = [0u8; 32];
294 rand::thread_rng().fill_bytes(&mut key);
295 key
296 }
297
298 fn generate_derived_key(len: usize) -> Vec<u8> {
300 let mut key = vec![0u8; len];
301 rand::thread_rng().fill_bytes(&mut key);
302 key
303 }
304
305 pub fn generate_secure_spi() -> u32 {
307 loop {
308 let mut spi_bytes = [0u8; 4];
309 rand::thread_rng().fill_bytes(&mut spi_bytes);
310 let spi = u32::from_be_bytes(spi_bytes);
311 if spi > 1 {
313 return spi;
314 }
315 }
316 }
317
318 fn generate_secure_iv() -> u64 {
320 let mut iv_bytes = [0u8; 8];
321 rand::thread_rng().fill_bytes(&mut iv_bytes);
322 u64::from_be_bytes(iv_bytes)
323 }
324
325 pub fn secure_clear(&mut self) {
329 self.psp_cfg.secure_clear();
331
332 for byte in &mut self.key {
334 unsafe {
335 std::ptr::write_volatile(byte, 0);
336 }
337 }
338
339 unsafe {
341 std::ptr::write_volatile(&mut self.iv, 0);
342 std::ptr::write_volatile(&mut self.vc, 0);
343 }
344 }
345
346 #[cfg(test)]
349 pub fn new_for_testing() -> PktContext {
350 PktContext {
351 psp_cfg: PspConfig {
352 master_keys: [[0; 32], [0; 32]],
353 spi: 1,
354 psp_encap: PspEncap::Transport,
355 crypto_alg: CryptoAlg::AesGcm128,
356 transport_crypt_off: 0,
357 ipv4_tunnel_crypt_off: 0,
358 ipv6_tunnel_crypt_off: 0,
359 include_vc: false,
360 },
361 key: vec![0; 16],
362 iv: 1,
363 vc: 0,
364 }
365 }
366}
367
368impl Default for PktContext {
369 fn default() -> PktContext {
370 PktContext::new()
371 }
372}
373
374impl Drop for PktContext {
375 fn drop(&mut self) {
378 self.secure_clear();
379 }
380}
381
382impl Drop for PspConfig {
383 fn drop(&mut self) {
386 self.secure_clear();
387 }
388}
389
390#[derive(thiserror::Error, Debug)]
392pub enum PspError {
393 #[error("PSP Crypto Error: {}", .0)]
396 CryptoError(#[from] error::Unspecified),
397
398 #[error("PSP Serialization Error")]
401 SerializeError(#[from] bincode::Error),
402
403 #[error("PSP No Ciphertext In PSP Packet")]
405 NoCiphertext,
406
407 #[error("Packet Parse Error")]
409 PacketParseError(#[from] etherparse::ReadError),
410
411 #[error("Invalid configuration: {0}")]
413 ConfigError(String),
414
415 #[error("Weak cryptographic key detected: {0}")]
417 WeakKey(String),
418
419 #[error("Invalid SPI value: {0}")]
421 InvalidSpi(u32),
422
423 #[error("Invalid PSP encapsulation type: {0}")]
425 InvalidPspEncap(String),
426
427 #[error("Invalid cryptographic algorithm: {0}")]
429 InvalidCryptoAlg(String),
430
431
432 #[error("Packet Write Error")]
434 PacketWriteError(#[from] etherparse::WriteError),
435
436 #[error("PSP Packet Build Error")]
438 PacketBuildError(#[from] io::Error),
439
440 #[error("Packet Could not be encapsulated in PSP: {}", .0)]
442 PacketEncapError(String),
443
444 #[error("PSP Packet Decap Error: {}", .0)]
448 PacketDecapError(String),
449
450 #[error("Invalid PSP Version: {}", .0)]
452 InvalidPspVersion(u8),
453
454 #[error("Invalid PSP Packet Size")]
457 InvalidPspPacketSize,
458
459 #[error("Unsupported Feature: {}", .0)]
461 Unsupported(String),
462}
463
464#[derive(Debug)]
482pub struct PspSocket {
483 options: PspSocketOptions,
484 udp_sock: Option<UdpSocket>,
485}
486
487impl PspSocket {
488 pub fn bind<A: ToSocketAddrs>(addr: A, opts: PspSocketOptions) -> io::Result<PspSocket> {
490 let udp_sock = UdpSocket::bind(addr)?;
491 let psp_sock = PspSocket {
492 options: opts,
493 udp_sock: Some(udp_sock),
494 };
495
496 Ok(psp_sock)
497 }
498
499 pub fn send_to<A: ToSocketAddrs>(&self, pkt: &[u8], addr: A) -> io::Result<()> {
501 let udp_sock = self
502 .udp_sock
503 .as_ref()
504 .ok_or(io::Error::new(io::ErrorKind::NotFound, "No UDP socket"))?;
505
506 let mut pkt_ctx = PktContext {
507 key: self.options.key.clone(),
508 psp_cfg: PspConfig {
509 spi: self.options.spi,
510 crypto_alg: self.options.algorithm,
511 transport_crypt_off: self.options.crypt_off,
512 ..Default::default()
513 },
514 ..Default::default()
515 };
516
517 let psp_pkt = psp_encap_pdu(&mut pkt_ctx, pkt, 0).map_err(|e| {
518 io::Error::new(
519 io::ErrorKind::Other,
520 format!("Error encapsulating packet: {:?}", e),
521 )
522 })?;
523 udp_sock.send_to(&psp_pkt, addr)?;
524 Ok(())
525 }
526
527 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, String)> {
529 let udp_sock = self
530 .udp_sock
531 .as_ref()
532 .ok_or(io::Error::new(io::ErrorKind::NotFound, "No UDP socket"))?;
533 let (size, addr) = udp_sock.recv_from(buf)?;
534
535 let mut pkt_ctx = PktContext {
536 key: self.options.key.clone(),
537 psp_cfg: PspConfig {
538 spi: self.options.spi,
539 crypto_alg: self.options.algorithm,
540 transport_crypt_off: self.options.crypt_off,
541 ..Default::default()
542 },
543 ..Default::default()
544 };
545
546 let decrypted = psp_decap_pdu(&mut pkt_ctx, &buf[..size]).map_err(|e| {
547 io::Error::new(
548 io::ErrorKind::Other,
549 format!("Error decapsulating packet: {:?}", e),
550 )
551 })?;
552 buf[..decrypted.len()].copy_from_slice(&decrypted);
553 Ok((decrypted.len(), addr.to_string()))
554 }
555}
556
557#[derive(Debug, Clone, Serialize, Deserialize, Default)]
559pub struct PspSocketOptions {
560 spi: u32,
562 key: PspDerivedKey,
564 algorithm: CryptoAlg,
566 crypt_off: u8,
568}
569
570impl PspSocketOptions {
571 pub fn new(spi: u32, key: &PspDerivedKey) -> PspSocketOptions {
572 PspSocketOptions {
573 spi,
574 key: key.clone(),
575 algorithm: CryptoAlg::AesGcm256,
576 crypt_off: 0,
577 }
578 }
579}
580
581const fn get_psp_version(alg: CryptoAlg) -> PspVersion {
582 match alg {
583 CryptoAlg::AesGcm128 => PspVersion::PspVer0,
584 CryptoAlg::AesGcm256 => PspVersion::PspVer1,
585 }
586}
587
588const fn get_psp_crypto_alg(ver: PspVersion) -> CryptoAlg {
589 match ver {
590 PspVersion::PspVer0 => CryptoAlg::AesGcm128,
591 PspVersion::PspVer1 => CryptoAlg::AesGcm256,
592 }
593}
594
595const fn select_master_key(spi: u32, keys: &[PspMasterKey]) -> &PspMasterKey {
596 if (spi >> PSP_SPI_KEY_SELECTOR_BIT) & 0x01 == 0 {
597 return &keys[0];
598 }
599 &keys[1]
600}
601
602fn derive_psp_key_128(
603 spi: u32,
604 crypto_alg: CryptoAlg,
605 master_keys: &[PspMasterKey],
606 counter: u8,
607) -> Vec<u8> {
608 use cmac::{Cmac, Mac};
609
610 let mut input_block: [u8; 16] = [0; 16];
611 input_block[3] = counter;
612 input_block[4] = 0x50;
613 input_block[5] = 0x76;
614
615 match crypto_alg {
616 CryptoAlg::AesGcm128 => {
617 input_block[6] = 0x30;
618 input_block[15] = 0x80;
619 }
620 CryptoAlg::AesGcm256 => {
621 input_block[6] = 0x31;
622 input_block[14] = 0x01;
623 input_block[15] = 0x00;
624 }
625 }
626
627 input_block[8] = ((spi >> 24) & 0xff) as u8;
628 input_block[9] = ((spi >> 16) & 0xff) as u8;
629 input_block[10] = ((spi >> 8) & 0xff) as u8;
630 input_block[11] = (spi & 0xff) as u8;
631
632 let key = select_master_key(spi, master_keys);
633
634 let mut mac = Cmac::<Aes256>::new(key.into());
635 mac.update(&input_block);
636 let result = mac.finalize();
637 result.into_bytes().to_vec()
638}
639
640pub fn derive_psp_key(spi: u32, crypto_alg: CryptoAlg, master_keys: &[PspMasterKey]) -> Vec<u8> {
642 let mut key = derive_psp_key_128(spi, crypto_alg, master_keys, 1);
643 if crypto_alg == CryptoAlg::AesGcm256 {
644 key.extend(derive_psp_key_128(spi, crypto_alg, master_keys, 2));
645 }
646 key
647}
648
649fn get_aesgcm_iv(spi: u32, iv: u64) -> [u8; 12] {
651 let mut gcm_iv: [u8; 12] = [0; 12];
652 gcm_iv[0..4].copy_from_slice(&spi.to_be_bytes());
653 gcm_iv[4..12].copy_from_slice(&iv.to_be_bytes());
654 gcm_iv
655}
656
657pub fn psp_encrypt(
682 algo: CryptoAlg,
683 key: &[u8],
684 iv: &[u8],
685 aad: &[u8],
686 cleartext: &[u8],
687 ciphertext: &mut [u8],
688) -> Result<(), PspError> {
689 debug!("psp_encrypt(): Key: {:02X?}", key);
690 debug!("psp_encrypt(): IV: {:02X?}", iv);
691 debug!("psp_encrypt(): AAD: {:02X?}", aad);
692 debug!("psp_encrypt(): Cleartext len: {}", cleartext.len());
693 debug!("psp_encrypt(): Ciphertext len: {}", ciphertext.len());
694
695 let mut in_out_buf = Vec::from(cleartext);
696
697 let unbound_key = match algo {
698 CryptoAlg::AesGcm128 => {
699 UnboundKey::new(&AES_128_GCM, key).map_err(|e| PspError::CryptoError(e))?
700 }
701 CryptoAlg::AesGcm256 => {
702 UnboundKey::new(&AES_256_GCM, key).map_err(|e| PspError::CryptoError(e))?
703 }
704 };
705 let counter = u64::from_be_bytes(iv[4..12].try_into().unwrap());
706 let nonce_seq = nonce_sequence::Counter64Builder::new()
707 .identifier(<[u8; 4]>::try_from(&iv[..4]).unwrap())
708 .counter(counter)
709 .build();
710 let mut sealing_key = SealingKey::new(unbound_key, nonce_seq);
711 let aad_content = Aad::from(aad);
712 sealing_key
713 .seal_in_place_append_tag(aad_content, &mut in_out_buf)
714 .map_err(|e| PspError::CryptoError(e))?;
715
716 ciphertext.copy_from_slice(&in_out_buf);
717
718 Ok(())
719}
720
721pub fn psp_decrypt(
747 algo: CryptoAlg,
748 key: &[u8],
749 iv: &[u8],
750 aad: &[u8],
751 ciphertext: &[u8],
752 cleartext: &mut [u8],
753) -> Result<(), PspError> {
754 debug!("psp_decrypt(): Key: {:02X?}", key);
755 debug!("psp_decrypt(): IV: {:02X?}", iv);
756 debug!("psp_decrypt(): AAD: {:02X?}", aad);
757 debug!("psp_encrypt(): Ciphertext len: {}", ciphertext.len());
758 debug!("psp_encrypt(): Cleartext len: {}", cleartext.len());
759
760 if ciphertext.is_empty() {
761 return Err(PspError::NoCiphertext);
762 }
763
764 let mut in_out_buf = Vec::from(ciphertext);
765
766 let unbound_key = match algo {
767 CryptoAlg::AesGcm128 => {
768 UnboundKey::new(&AES_128_GCM, key).map_err(|e| PspError::CryptoError(e))?
769 }
770 CryptoAlg::AesGcm256 => {
771 UnboundKey::new(&AES_256_GCM, key).map_err(|e| PspError::CryptoError(e))?
772 }
773 };
774 let counter = u64::from_be_bytes(iv[4..12].try_into().unwrap());
775 let nonce_seq = nonce_sequence::Counter64Builder::new()
776 .identifier(<[u8; 4]>::try_from(&iv[..4]).unwrap())
777 .counter(counter)
778 .build();
779 let mut opening_key = OpeningKey::new(unbound_key, nonce_seq);
780 let aad_content = Aad::from(aad);
781 opening_key
782 .open_in_place(aad_content, &mut in_out_buf)
783 .map_err(|e| PspError::CryptoError(e))?;
784
785 let pt_len = in_out_buf.len() - PSP_ICV_SIZE;
789 let drop_offset = pt_len - cleartext.len();
790 cleartext.copy_from_slice(&in_out_buf[drop_offset..ciphertext.len() - PSP_ICV_SIZE]);
791
792 Ok(())
793}
794
795pub fn psp_encap_pdu(
826 pkt_ctx: &mut PktContext,
827 in_pdu: &[u8],
828 next_protocol: u8,
829) -> Result<Vec<u8>, PspError> {
830 let crypt_off = usize::from(pkt_ctx.psp_cfg.transport_crypt_off) * PSP_CRYPT_OFFSET_UNITS;
831 let mut payload_crypt_off = crypt_off;
832 let mut encrypted_vc = false;
833
834 if pkt_ctx.psp_cfg.include_vc {
835 if crypt_off >= PSP_VC_SIZE {
836 payload_crypt_off -= PSP_VC_SIZE;
837 } else {
838 encrypted_vc = true;
839 payload_crypt_off = 0;
840 }
841 }
842 if crypt_off > in_pdu.len() {
843 return Err(PspError::PacketEncapError(
844 "Crypt offset too big".to_string(),
845 ));
846 }
847 debug!("encap: crypt_off: {crypt_off}");
848 debug!("encap: payload_crypt_off: {payload_crypt_off}");
849
850 let mut psp_encap_len = PspPacket::minimum_packet_size() + PSP_ICV_SIZE;
857 if pkt_ctx.psp_cfg.include_vc {
858 psp_encap_len += PSP_VC_SIZE;
859 }
860 let out_pkt_len = psp_encap_len + in_pdu.len();
861 let mut out_pkt = Vec::<u8>::with_capacity(out_pkt_len);
862
863 let mut flags = PspHeaderFlags::default();
864 flags.set_version(get_psp_version(pkt_ctx.psp_cfg.crypto_alg) as u8);
865 flags.set_v(pkt_ctx.psp_cfg.include_vc);
866
867 let psp_hdr = &PspHeader {
868 next_hdr: next_protocol,
869 hdr_ext_len: match pkt_ctx.psp_cfg.include_vc {
870 true => 2,
871 false => 1,
872 },
873 crypt_off: pkt_ctx.psp_cfg.transport_crypt_off,
874 flags,
875 spi: pkt_ctx.psp_cfg.spi,
876 iv: pkt_ctx.iv,
877 };
878
879 let start_of_psp_hdr = out_pkt.len();
880 let encoder = bincode::DefaultOptions::new()
881 .with_big_endian()
882 .with_fixint_encoding();
883 let psp_buf = encoder.serialize(psp_hdr)?;
884 out_pkt.extend_from_slice(&psp_buf);
885
886 let end_of_iv = out_pkt.len();
887 let start_of_crypto_region = end_of_iv + crypt_off;
888
889 if flags.v() {
890 out_pkt.extend_from_slice(&encoder.serialize(&pkt_ctx.vc)?);
891 }
892 let start_of_payload_region = out_pkt.len();
893
894 let gcm_iv = get_aesgcm_iv(pkt_ctx.psp_cfg.spi, pkt_ctx.iv);
895 pkt_ctx.iv += 1;
896
897 out_pkt.extend_from_slice(&in_pdu[..payload_crypt_off]);
898 out_pkt.resize(out_pkt_len, 0);
899 let aad = out_pkt[start_of_psp_hdr..start_of_crypto_region].to_vec();
900
901 if encrypted_vc {
902 let mut cleartext: Vec<u8> = Vec::with_capacity(in_pdu.len() + PSP_VC_SIZE);
903 cleartext.extend_from_slice(&out_pkt[start_of_crypto_region..start_of_payload_region]);
904 cleartext.extend_from_slice(in_pdu);
905
906 let ciphertext = &mut out_pkt[start_of_crypto_region..];
907
908 psp_encrypt(
909 pkt_ctx.psp_cfg.crypto_alg,
910 &pkt_ctx.key,
911 &gcm_iv,
912 &aad,
913 &cleartext,
914 ciphertext,
915 )?;
916 } else {
917 let cleartext = &in_pdu[payload_crypt_off..];
919
920 let ciphertext = &mut out_pkt[start_of_crypto_region..];
921
922 psp_encrypt(
923 pkt_ctx.psp_cfg.crypto_alg,
924 &pkt_ctx.key,
925 &gcm_iv,
926 &aad,
927 cleartext,
928 ciphertext,
929 )?;
930 }
931
932 Ok(out_pkt)
933}
934
935pub fn psp_transport_encap(pkt_ctx: &mut PktContext, in_pkt: &[u8]) -> Result<Vec<u8>, PspError> {
972 let (in_eth, in_eth_payload) = Ethernet2Header::from_slice(in_pkt)?;
973 match in_eth.ether_type {
974 ether_type::IPV4 => (),
975 ether_type::IPV6 => (),
976 _ => {
977 return Err(PspError::PacketEncapError(
978 "Unsupported input packet type".to_string(),
979 ))
980 }
981 }
982
983 let (in_ip, next_protocol, in_ip_payload) = IpHeader::from_slice(in_eth_payload)?;
984
985 let crypt_off = usize::from(pkt_ctx.psp_cfg.transport_crypt_off) * PSP_CRYPT_OFFSET_UNITS;
986 let mut payload_crypt_off = crypt_off;
987 let mut encrypted_vc = false;
988
989 if pkt_ctx.psp_cfg.include_vc {
990 if crypt_off >= PSP_VC_SIZE {
991 payload_crypt_off -= PSP_VC_SIZE;
992 } else {
993 encrypted_vc = true;
994 payload_crypt_off = 0;
995 }
996 }
997 if crypt_off > in_ip_payload.len() {
998 return Err(PspError::PacketEncapError(
999 "Crypt offset too big".to_string(),
1000 ));
1001 }
1002 debug!("transport_encap: crypt_off: {crypt_off}");
1003 debug!("transport_encap: payload_crypt_off: {payload_crypt_off}");
1004
1005 let mut psp_encap_len = PspPacket::minimum_packet_size() + PSP_ICV_SIZE;
1014 if pkt_ctx.psp_cfg.include_vc {
1015 psp_encap_len += PSP_VC_SIZE;
1016 }
1017 let psp_udp_encap_len = psp_encap_len + UdpHeader::SERIALIZED_SIZE;
1018 let out_pkt_len = in_pkt.len() + psp_udp_encap_len;
1019 let mut out_pkt = Vec::<u8>::with_capacity(out_pkt_len);
1020
1021 in_eth.write(&mut out_pkt)?;
1022
1023 let mut out_ip = in_ip;
1024 out_ip.set_next_headers(ip_number::UDP);
1025 out_ip
1026 .set_payload_len(in_ip_payload.len() + psp_udp_encap_len)
1027 .map_err(|err| PspError::PacketEncapError(format!("Failed to encapsulate packet: {}", err)))?;
1028 out_ip.write(&mut out_pkt)?;
1029
1030 let out_udp = UdpHeader::without_ipv4_checksum(
1031 PSP_UDP_PORT,
1032 PSP_UDP_PORT,
1033 in_ip_payload.len() + psp_encap_len,
1034 )
1035 .map_err(|err| PspError::PacketEncapError(format!("Failed to encapsulate packet: {}", err)))?;
1036
1037 out_udp.write(&mut out_pkt)?;
1038
1039 let mut flags = PspHeaderFlags::default();
1040 flags.set_version(get_psp_version(pkt_ctx.psp_cfg.crypto_alg) as u8);
1041 flags.set_v(pkt_ctx.psp_cfg.include_vc);
1042
1043 let psp_hdr = &PspHeader {
1044 next_hdr: next_protocol,
1045 hdr_ext_len: match pkt_ctx.psp_cfg.include_vc {
1046 true => 2,
1047 false => 1,
1048 },
1049 crypt_off: pkt_ctx.psp_cfg.transport_crypt_off,
1050 flags,
1051 spi: pkt_ctx.psp_cfg.spi,
1052 iv: pkt_ctx.iv,
1053 };
1054
1055 let start_of_psp_hdr = out_pkt.len();
1056 let encoder = bincode::DefaultOptions::new()
1057 .with_big_endian()
1058 .with_fixint_encoding();
1059 let psp_buf = encoder.serialize(psp_hdr)?;
1060 out_pkt.extend_from_slice(&psp_buf);
1061
1062 let end_of_iv = out_pkt.len();
1063 let start_of_crypto_region = end_of_iv + crypt_off;
1064
1065 if flags.v() {
1066 out_pkt.extend_from_slice(&encoder.serialize(&pkt_ctx.vc)?);
1067 }
1068 let start_of_payload_region = out_pkt.len();
1069
1070 let gcm_iv = get_aesgcm_iv(pkt_ctx.psp_cfg.spi, pkt_ctx.iv);
1071 pkt_ctx.iv += 1;
1072
1073 out_pkt.extend_from_slice(&in_ip_payload[..payload_crypt_off]);
1074 out_pkt.resize(out_pkt_len, 0);
1075 let aad = out_pkt[start_of_psp_hdr..start_of_crypto_region].to_vec();
1076
1077 if encrypted_vc {
1078 let mut cleartext: Vec<u8> = Vec::with_capacity(in_ip_payload.len() + PSP_VC_SIZE);
1079 cleartext.extend_from_slice(&out_pkt[start_of_crypto_region..start_of_payload_region]);
1080 cleartext.extend_from_slice(in_ip_payload);
1081
1082 let ciphertext = &mut out_pkt[start_of_crypto_region..];
1083
1084 psp_encrypt(
1085 pkt_ctx.psp_cfg.crypto_alg,
1086 &pkt_ctx.key,
1087 &gcm_iv,
1088 &aad,
1089 &cleartext,
1090 ciphertext,
1091 )?;
1092 } else {
1093 let cleartext = &in_ip_payload[payload_crypt_off..];
1095
1096 let ciphertext = &mut out_pkt[start_of_crypto_region..];
1097
1098 psp_encrypt(
1099 pkt_ctx.psp_cfg.crypto_alg,
1100 &pkt_ctx.key,
1101 &gcm_iv,
1102 &aad,
1103 cleartext,
1104 ciphertext,
1105 )?;
1106 }
1107
1108 Ok(out_pkt)
1109}
1110
1111pub fn psp_tunnel_encap(pkt_ctx: &mut PktContext, in_pkt: &[u8]) -> Result<Vec<u8>, PspError> {
1148 let (in_eth, in_eth_payload) = Ethernet2Header::from_slice(in_pkt)?;
1149 let (psp_next_protocol, tun_hdr_size) = match in_eth.ether_type {
1150 ether_type::IPV4 => (ip_number::IPV4, Ipv4Header::SERIALIZED_SIZE),
1151 ether_type::IPV6 => (ip_number::IPV6, Ipv6Header::SERIALIZED_SIZE),
1152 _ => {
1153 return Err(PspError::PacketEncapError(
1154 "Unsupported input packet type".to_string(),
1155 ))
1156 }
1157 };
1158
1159 let psp_payload = in_eth_payload;
1160 let psp_payload_len = psp_payload.len();
1161
1162 let (in_ip, _, _) = IpHeader::from_slice(in_eth_payload)?;
1163
1164 let crypt_off_cfg_val = match psp_next_protocol {
1165 ip_number::IPV4 => usize::from(pkt_ctx.psp_cfg.ipv4_tunnel_crypt_off),
1166 ip_number::IPV6 => usize::from(pkt_ctx.psp_cfg.ipv6_tunnel_crypt_off),
1167 _ => 0,
1168 };
1169 let crypt_off = crypt_off_cfg_val * PSP_CRYPT_OFFSET_UNITS;
1170 let mut payload_crypt_off = crypt_off;
1171 let mut encrypted_vc = false;
1172 if pkt_ctx.psp_cfg.include_vc {
1173 if crypt_off >= PSP_VC_SIZE {
1174 payload_crypt_off -= PSP_VC_SIZE;
1175 } else {
1176 encrypted_vc = true;
1177 }
1178 }
1179 if payload_crypt_off > in_eth_payload.len() {
1180 return Err(PspError::PacketEncapError(
1181 "Crypto offset too big".to_string(),
1182 ));
1183 }
1184
1185 let mut psp_encap_len = PspPacket::minimum_packet_size() + PSP_ICV_SIZE;
1195 if pkt_ctx.psp_cfg.include_vc {
1196 psp_encap_len += PSP_VC_SIZE;
1197 }
1198 let psp_udp_encap_len = psp_encap_len + UdpHeader::SERIALIZED_SIZE;
1199 let psp_udp_ip_encap_len = psp_udp_encap_len + tun_hdr_size;
1200 let out_pkt_len = in_pkt.len() + psp_udp_ip_encap_len;
1201 let mut out_pkt = Vec::<u8>::with_capacity(out_pkt_len);
1202
1203 in_eth.write(&mut out_pkt)?;
1204
1205 let mut out_ip = in_ip;
1206 out_ip.set_next_headers(ip_number::UDP);
1207 out_ip
1208 .set_payload_len(psp_payload_len + psp_udp_encap_len)
1209 .map_err(|err| PspError::PacketEncapError(format!("Failed to encapsulate packet: {}", err)))?;
1210 out_ip.write(&mut out_pkt)?;
1211
1212 let out_udp = UdpHeader::without_ipv4_checksum(
1213 PSP_UDP_PORT,
1214 PSP_UDP_PORT,
1215 psp_payload_len + psp_encap_len,
1216 )
1217 .map_err(|err| PspError::PacketEncapError(format!("Failed to encapsulate packet: {}", err)))?;
1218
1219 out_udp.write(&mut out_pkt)?;
1220
1221 let mut flags = PspHeaderFlags::default();
1222 flags.set_version(get_psp_version(pkt_ctx.psp_cfg.crypto_alg) as u8);
1223 flags.set_v(pkt_ctx.psp_cfg.include_vc);
1224
1225 let psp_hdr = &PspHeader {
1226 next_hdr: psp_next_protocol,
1227 hdr_ext_len: match pkt_ctx.psp_cfg.include_vc {
1228 true => 2,
1229 false => 1,
1230 },
1231 crypt_off: crypt_off_cfg_val as u8,
1232 flags,
1233 spi: pkt_ctx.psp_cfg.spi,
1234 iv: pkt_ctx.iv,
1235 };
1236
1237 let start_of_psp_hdr = out_pkt.len();
1238
1239 let encoder = bincode::DefaultOptions::new()
1240 .with_big_endian()
1241 .with_fixint_encoding();
1242 let psp_buf = encoder.serialize(psp_hdr)?;
1243 out_pkt.extend_from_slice(&psp_buf);
1244
1245 let end_of_iv = out_pkt.len();
1246 let start_of_crypto_region = end_of_iv + crypt_off;
1247
1248 if flags.v() {
1249 out_pkt.extend_from_slice(&encoder.serialize(&pkt_ctx.vc)?);
1250 }
1251
1252 let start_of_payload_region = out_pkt.len();
1253
1254 let gcm_iv = get_aesgcm_iv(pkt_ctx.psp_cfg.spi, pkt_ctx.iv);
1255 pkt_ctx.iv += 1;
1256
1257 out_pkt.extend_from_slice(&psp_payload[..payload_crypt_off]);
1258 out_pkt.resize(out_pkt_len, 0);
1259 let aad = out_pkt[start_of_psp_hdr..start_of_crypto_region].to_vec();
1260
1261 if encrypted_vc {
1262 let mut cleartext: Vec<u8> = Vec::with_capacity(psp_payload.len() + PSP_VC_SIZE);
1263 cleartext.extend_from_slice(&out_pkt[start_of_crypto_region..start_of_payload_region]);
1264 cleartext.extend_from_slice(psp_payload);
1265
1266 let ciphertext = &mut out_pkt[start_of_crypto_region..];
1267
1268 psp_encrypt(
1269 pkt_ctx.psp_cfg.crypto_alg,
1270 &pkt_ctx.key,
1271 &gcm_iv,
1272 &aad,
1273 &cleartext,
1274 ciphertext,
1275 )?;
1276 } else {
1277 let cleartext = &psp_payload[payload_crypt_off..];
1279
1280 let ciphertext = &mut out_pkt[start_of_crypto_region..];
1281
1282 psp_encrypt(
1283 pkt_ctx.psp_cfg.crypto_alg,
1284 &pkt_ctx.key,
1285 &gcm_iv,
1286 &aad,
1287 cleartext,
1288 ciphertext,
1289 )?;
1290 }
1291
1292 Ok(out_pkt)
1293}
1294
1295pub fn psp_decap_eth(pkt_ctx: &mut PktContext, in_pkt: &[u8]) -> Result<Vec<u8>, PspError> {
1299 let parsed_pkt = PacketHeaders::from_ethernet_slice(in_pkt)?;
1300 match parsed_pkt.transport {
1301 None => Err(PspError::PacketDecapError("No UDP header".to_string())),
1302 _ => Ok(()),
1303 }?;
1304
1305 let psp_buf = parsed_pkt.payload;
1306
1307 let in_psp = PspPacket::new(psp_buf).ok_or(PspError::PacketDecapError(
1308 "Error parsing PSP header".to_string(),
1309 ))?;
1310
1311 match in_psp.get_next_hdr() {
1312 ip_number::IPV4 | ip_number::IPV6 => psp_tunnel_decap(pkt_ctx, in_pkt),
1313 _ => psp_transport_decap(pkt_ctx, in_pkt),
1314 }
1315}
1316
1317pub fn psp_transport_decap(pkt_ctx: &mut PktContext, in_pkt: &[u8]) -> Result<Vec<u8>, PspError> {
1357 let parsed_pkt = PacketHeaders::from_ethernet_slice(in_pkt)?;
1358 match parsed_pkt.transport {
1359 None => Err(PspError::PacketDecapError("No UDP header".to_string())),
1360 _ => Ok(()),
1361 }?;
1362
1363 let psp_buf = parsed_pkt.payload;
1364
1365 let in_psp = PspPacket::new(psp_buf).ok_or(PspError::PacketDecapError(
1366 "Error parsing PSP header".to_string(),
1367 ))?;
1368
1369 let payload = in_psp.payload();
1370 if payload.len() < PSP_ICV_SIZE {
1371 return Err(PspError::InvalidPspPacketSize);
1372 }
1373
1374 let crypt_off = usize::from(in_psp.get_crypt_offset()) * PSP_CRYPT_OFFSET_UNITS;
1375 debug!("transport_decap: crypt_off: {crypt_off}");
1376 let mut payload_crypt_off = crypt_off;
1377 if in_psp.get_v() == 1 {
1378 if crypt_off >= PSP_VC_SIZE {
1379 payload_crypt_off -= PSP_VC_SIZE;
1380 } else {
1381 payload_crypt_off = 0;
1382 }
1383 }
1384 if payload_crypt_off > payload.len() {
1385 return Err(PspError::PacketDecapError(
1386 "Invalid crypto offset".to_string(),
1387 ));
1388 }
1389
1390 let vc_len = match in_psp.get_v() {
1397 0 => 0,
1398 _ => PSP_VC_SIZE,
1399 };
1400 let psp_encap_len = PspPacket::minimum_packet_size() + vc_len + PSP_ICV_SIZE;
1401 let psp_and_udp_encap_len = UdpHeader::SERIALIZED_SIZE + psp_encap_len;
1402 let out_pkt_len = in_pkt.len() - psp_and_udp_encap_len;
1403 let mut out_pkt = Vec::<u8>::with_capacity(out_pkt_len);
1404
1405 if let Some(eth) = parsed_pkt.link {
1406 eth.write(&mut out_pkt)?;
1407 }
1408 if let Some(ip) = parsed_pkt.ip {
1409 let mut out_ip = ip;
1410 let out_ip_len = parsed_pkt.payload.len() - psp_encap_len;
1411 out_ip
1412 .set_payload_len(out_ip_len)
1413 .map_err(|err| PspError::PacketDecapError(format!("Failed to decapsulate packet: {}", err)))?;
1414 out_ip.set_next_headers(in_psp.get_next_hdr());
1415 out_ip.write(&mut out_pkt)?;
1416 }
1417
1418 pkt_ctx.psp_cfg.crypto_alg = get_psp_crypto_alg(in_psp.get_version().try_into()?);
1419
1420 let aad_len: usize = usize::from(PSP_HDR_FIXED_LEN) + crypt_off;
1421 let aad = parsed_pkt.payload[..aad_len].to_vec();
1422
1423 let spi = in_psp.get_spi();
1424 pkt_ctx.psp_cfg.spi = spi;
1425 let gcm_iv = get_aesgcm_iv(spi, in_psp.get_iv());
1426
1427 pkt_ctx.key = derive_psp_key(
1428 pkt_ctx.psp_cfg.spi,
1429 pkt_ctx.psp_cfg.crypto_alg,
1430 &pkt_ctx.psp_cfg.master_keys,
1431 );
1432
1433 let ciphertext = &parsed_pkt.payload[aad_len..];
1434 out_pkt.extend_from_slice(&in_psp.payload()[..payload_crypt_off]);
1435
1436 let start_of_decrypt_region = out_pkt.len();
1437 out_pkt.resize(out_pkt_len, 0);
1438 let cleartext = &mut out_pkt[start_of_decrypt_region..];
1439
1440 psp_decrypt(
1441 pkt_ctx.psp_cfg.crypto_alg,
1442 &pkt_ctx.key,
1443 &gcm_iv,
1444 &aad,
1445 ciphertext,
1446 cleartext,
1447 )?;
1448
1449 Ok(out_pkt)
1450}
1451
1452pub fn psp_tunnel_decap(pkt_ctx: &mut PktContext, in_pkt: &[u8]) -> Result<Vec<u8>, PspError> {
1492 let parsed_pkt = PacketHeaders::from_ethernet_slice(in_pkt)?;
1493
1494 let eth = parsed_pkt.link.ok_or(PspError::PacketDecapError(
1495 "Unsupported packet type".to_string(),
1496 ))?;
1497
1498 let ip_hdr = parsed_pkt.ip.ok_or(PspError::PacketDecapError(
1499 "Unsupported packet type".to_string(),
1500 ))?;
1501 let ip_hdr_size = ip_hdr.header_len();
1502
1503 match parsed_pkt.transport {
1504 Some(TransportHeader::Udp(_)) => Ok(()),
1505 _ => Err(PspError::PacketDecapError("No UDP header".to_string())),
1506 }?;
1507
1508 let psp_buf = parsed_pkt.payload;
1509 let in_psp = PspPacket::new(psp_buf).ok_or(PspError::PacketDecapError(
1510 "Error parsing PSP header".to_string(),
1511 ))?;
1512
1513 let payload = in_psp.payload();
1514 if payload.len() < PSP_ICV_SIZE {
1515 return Err(PspError::InvalidPspPacketSize);
1516 }
1517
1518 let crypt_off = usize::from(in_psp.get_crypt_offset()) * PSP_CRYPT_OFFSET_UNITS;
1519 let mut payload_crypt_off = crypt_off;
1520 if in_psp.get_v() == 1 {
1521 if crypt_off >= PSP_VC_SIZE {
1522 payload_crypt_off -= PSP_VC_SIZE;
1523 } else {
1524 payload_crypt_off = 0;
1525 }
1526 }
1527 if payload_crypt_off > payload.len() {
1528 return Err(PspError::PacketDecapError(
1529 "Invalid crypto offset".to_string(),
1530 ));
1531 }
1532
1533 let vc_len = match in_psp.get_v() {
1543 0 => 0,
1544 _ => PSP_VC_SIZE,
1545 };
1546 let psp_encap_len = PspPacket::minimum_packet_size() + vc_len + PSP_ICV_SIZE;
1547 let psp_udp_encap_len = UdpHeader::SERIALIZED_SIZE + psp_encap_len;
1548 let psp_udp_ip_encap_len = ip_hdr_size + psp_udp_encap_len;
1549 let out_pkt_len = in_pkt.len() - psp_udp_ip_encap_len;
1550 let mut out_pkt = Vec::<u8>::with_capacity(out_pkt_len);
1551
1552 eth.write(&mut out_pkt)?;
1553
1554 pkt_ctx.psp_cfg.crypto_alg = get_psp_crypto_alg(in_psp.get_version().try_into()?);
1555
1556 let aad_len: usize = usize::from(PSP_HDR_FIXED_LEN) + crypt_off;
1558 let aad = parsed_pkt.payload[..aad_len].to_vec();
1559
1560 let spi = in_psp.get_spi();
1561 pkt_ctx.psp_cfg.spi = spi;
1562 let gcm_iv = get_aesgcm_iv(spi, in_psp.get_iv());
1563
1564 pkt_ctx.key = derive_psp_key(
1565 pkt_ctx.psp_cfg.spi,
1566 pkt_ctx.psp_cfg.crypto_alg,
1567 &pkt_ctx.psp_cfg.master_keys,
1568 );
1569
1570 let ciphertext = &parsed_pkt.payload[aad_len..];
1571 out_pkt.extend_from_slice(&in_psp.payload()[..payload_crypt_off]);
1572
1573 let start_of_decrypt_region = out_pkt.len();
1574 out_pkt.resize(out_pkt_len, 0);
1575 let cleartext = &mut out_pkt[start_of_decrypt_region..];
1576
1577 psp_decrypt(
1578 pkt_ctx.psp_cfg.crypto_alg,
1579 &pkt_ctx.key,
1580 &gcm_iv,
1581 &aad,
1582 ciphertext,
1583 cleartext,
1584 )?;
1585
1586 Ok(out_pkt)
1587}
1588
1589pub fn psp_decap_pdu(pkt_ctx: &mut PktContext, in_pdu: &[u8]) -> Result<Vec<u8>, PspError> {
1621 let in_psp = PspPacket::new(in_pdu).ok_or(PspError::PacketDecapError(
1622 "Error parsing PSP header".to_string(),
1623 ))?;
1624
1625 let payload = in_psp.payload();
1626 if payload.len() < PSP_ICV_SIZE {
1627 return Err(PspError::InvalidPspPacketSize);
1628 }
1629
1630 let crypt_off = usize::from(in_psp.get_crypt_offset()) * PSP_CRYPT_OFFSET_UNITS;
1631 debug!("transport_decap: crypt_off: {crypt_off}");
1632 let mut payload_crypt_off = crypt_off;
1633 if in_psp.get_v() == 1 {
1634 if crypt_off >= PSP_VC_SIZE {
1635 payload_crypt_off -= PSP_VC_SIZE;
1636 } else {
1637 payload_crypt_off = 0;
1638 }
1639 }
1640 if payload_crypt_off > payload.len() {
1641 return Err(PspError::PacketDecapError(
1642 "Invalid crypto offset".to_string(),
1643 ));
1644 }
1645
1646 let vc_len = match in_psp.get_v() {
1650 0 => 0,
1651 _ => PSP_VC_SIZE,
1652 };
1653 let psp_encap_len = PspPacket::minimum_packet_size() + vc_len + PSP_ICV_SIZE;
1654 let out_pkt_len = in_pdu.len() - psp_encap_len;
1655 let mut out_pkt = Vec::<u8>::with_capacity(out_pkt_len);
1656
1657 pkt_ctx.psp_cfg.crypto_alg = get_psp_crypto_alg(in_psp.get_version().try_into()?);
1658
1659 let aad_len: usize = usize::from(PSP_HDR_FIXED_LEN) + crypt_off;
1660 let aad = in_pdu[..aad_len].to_vec();
1661
1662 let spi = in_psp.get_spi();
1663 pkt_ctx.psp_cfg.spi = spi;
1664 let gcm_iv = get_aesgcm_iv(spi, in_psp.get_iv());
1665
1666 debug!("decap_pdu: spi: {:08X}", pkt_ctx.psp_cfg.spi);
1667 debug!("decap_pdu: crypto_alg: {}", pkt_ctx.psp_cfg.crypto_alg);
1668 debug!("decap_pdu: iv: {}", pkt_ctx.iv);
1669 debug!("decap_pdu: key: {:?}", &pkt_ctx.key);
1670
1671 let ciphertext = &in_pdu[aad_len..];
1678 out_pkt.extend_from_slice(&in_psp.payload()[..payload_crypt_off]);
1679
1680 let start_of_decrypt_region = out_pkt.len();
1681 out_pkt.resize(out_pkt_len, 0);
1682 let cleartext = &mut out_pkt[start_of_decrypt_region..];
1683
1684 psp_decrypt(
1685 pkt_ctx.psp_cfg.crypto_alg,
1686 &pkt_ctx.key,
1687 &gcm_iv,
1688 &aad,
1689 ciphertext,
1690 cleartext,
1691 )?;
1692
1693 Ok(out_pkt)
1694}
1695
1696#[cfg(test)]
1697mod tests {
1698 use super::*;
1699 use crate::packet::psp::PspPacket;
1700 use etherparse::{EtherType, IpNumber, PacketBuilder, TransportHeader};
1701
1702 #[test]
1703 fn test_psp_version_try_from() {
1704 assert!(PspVersion::try_from(0).is_ok());
1705 assert!(PspVersion::try_from(1).is_ok());
1706 assert!(PspVersion::try_from(2).is_err());
1707 }
1708
1709 #[test]
1710 fn check_psp_header_builder() {
1711 let hdr = PspHeaderBuilder::default()
1712 .next_hdr(17)
1713 .spi(0x12345678)
1714 .iv(0x12345678_9ABCDEF0)
1715 .build()
1716 .unwrap();
1717
1718 assert_eq!(hdr.spi, 0x12345678);
1719 assert_eq!(hdr.iv, 0x12345678_9ABCDEF0);
1720 assert_eq!(hdr.next_hdr, 17);
1721 assert_eq!(hdr.flags.0, 0x01u8);
1722 }
1723
1724 #[test]
1725 fn test_derive_psp_key_128() {
1726 let mut master_keys = [[0u8; PSP_MASTER_KEY_SIZE]; 2];
1727 master_keys[0] = [
1728 0x34, 0x44, 0x8A, 0x06, 0x42, 0x92, 0x60, 0x1B, 0x11, 0xA0, 0x97, 0x8F, 0x56, 0xA2,
1729 0xd3, 0x4c, 0xf3, 0xfc, 0x35, 0xed, 0xe1, 0xa6, 0xbc, 0x04, 0xf8, 0xdb, 0x3e, 0x52,
1730 0x43, 0xa2, 0xb0, 0xca,
1731 ];
1732 master_keys[1] = [
1733 0x56, 0x39, 0x52, 0x56, 0x5d, 0x3a, 0x78, 0xae, 0x77, 0x3e, 0xc1, 0xb7, 0x79, 0xf2,
1734 0xf2, 0xd9, 0x9f, 0x4a, 0x7f, 0x53, 0xa6, 0xfb, 0xb9, 0xb0, 0x7d, 0x5b, 0x71, 0xf3,
1735 0x93, 0x64, 0xd7, 0x39,
1736 ];
1737
1738 let spi = 0x12345678;
1739 let expected: [u8; 16] = [
1740 0x96, 0xc2, 0x2d, 0xc7, 0x99, 0x19, 0x80, 0x90, 0xb7, 0x4b, 0x70, 0xae, 0x46, 0x8e,
1741 0x4e, 0x30,
1742 ];
1743
1744 let derived_key = derive_psp_key_128(spi, CryptoAlg::AesGcm128, &master_keys, 1);
1745 assert_eq!(expected.to_vec(), derived_key);
1746
1747 let spi = 0x9A345678;
1748 let expected: [u8; 16] = [
1749 0x39, 0x46, 0xda, 0x25, 0x54, 0xea, 0xe4, 0x6a, 0xd1, 0xef, 0x77, 0xa6, 0x43, 0x72,
1750 0xed, 0xc4,
1751 ];
1752
1753 let derived_key = derive_psp_key_128(spi, CryptoAlg::AesGcm128, &master_keys, 1);
1754 assert_eq!(expected.to_vec(), derived_key);
1755 }
1756
1757 #[test]
1758 fn test_derive_psp_key() {
1759 let mut master_keys = [[0u8; PSP_MASTER_KEY_SIZE]; 2];
1760 master_keys[0] = [
1761 0x34, 0x44, 0x8A, 0x06, 0x42, 0x92, 0x60, 0x1B, 0x11, 0xA0, 0x97, 0x8F, 0x56, 0xA2,
1762 0xd3, 0x4c, 0xf3, 0xfc, 0x35, 0xed, 0xe1, 0xa6, 0xbc, 0x04, 0xf8, 0xdb, 0x3e, 0x52,
1763 0x43, 0xa2, 0xb0, 0xca,
1764 ];
1765 let spi = 0x12345678;
1766 let crypto_alg = CryptoAlg::AesGcm128;
1767 let expected: [u8; 16] = [
1768 0x96, 0xc2, 0x2d, 0xc7, 0x99, 0x19, 0x80, 0x90, 0xb7, 0x4b, 0x70, 0xae, 0x46, 0x8e,
1769 0x4e, 0x30,
1770 ];
1771 let derived_key = derive_psp_key(spi, crypto_alg, &master_keys);
1772 assert_eq!(derived_key.len(), 16);
1773 assert_eq!(derived_key, expected);
1774
1775 let crypto_alg = CryptoAlg::AesGcm256;
1776 let expected: [u8; 32] = [
1777 0x2b, 0x7d, 0x72, 0x07, 0x4e, 0x42, 0xca, 0x33, 0x44, 0x87, 0xf2, 0x99, 0x0e, 0x3f,
1778 0x8c, 0x40, 0x37, 0xe4, 0x36, 0xf3, 0x82, 0x83, 0x44, 0x9b, 0x76, 0x46, 0x3e, 0x9b,
1779 0x7f, 0xb2, 0xe3, 0xde,
1780 ];
1781 let derived_key = derive_psp_key(spi, crypto_alg, &master_keys);
1782 assert_eq!(derived_key.len(), 32);
1783 assert_eq!(derived_key, expected);
1784 }
1785
1786 #[test]
1787 fn test_psp_encrypt() -> Result<(), Box<dyn std::error::Error>> {
1788 let mut pkt_ctx = PktContext::new();
1789 pkt_ctx.psp_cfg.crypto_alg = CryptoAlg::AesGcm128;
1790 pkt_ctx.key = vec![
1791 0x96, 0xc2, 0x2d, 0xc7, 0x99, 0x19, 0x80, 0x90, 0xb7, 0x4b, 0x70, 0xae, 0x46, 0x8e,
1792 0x4e, 0x30,
1793 ];
1794 let mut psp_hdr = PspHeader::default();
1795 psp_hdr.next_hdr = 6;
1796 psp_hdr.spi = 0x12345678;
1797 psp_hdr.iv = 0x12345678_9ABCDEFF;
1798 let aad = bincode::DefaultOptions::new()
1799 .with_fixint_encoding()
1800 .with_big_endian()
1801 .serialize(&psp_hdr)?;
1802
1803 let gcm_iv = get_aesgcm_iv(psp_hdr.spi, psp_hdr.iv);
1804
1805 let cleartext = vec![0u8; 256];
1806 let mut ciphertext = vec![0u8; 256 + PSP_ICV_SIZE];
1807
1808 let res = psp_encrypt(
1809 pkt_ctx.psp_cfg.crypto_alg,
1810 &pkt_ctx.key,
1811 &gcm_iv,
1812 &aad,
1813 &cleartext,
1814 &mut ciphertext,
1815 );
1816 assert!(res.is_ok());
1817 assert_ne!(ciphertext, cleartext);
1818
1819 Ok(())
1820 }
1821
1822 #[test]
1823 fn check_transport_encap() -> Result<(), Box<dyn std::error::Error>> {
1824 let builder = PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
1825 .ipv4([192, 168, 1, 1], [192, 168, 1, 2], 32)
1826 .udp(21, 1234);
1827 let payload = [1, 2, 3, 4, 5, 6, 7, 8];
1828 let mut in_pkt = Vec::<u8>::with_capacity(builder.size(payload.len()));
1829 builder.write(&mut in_pkt, &payload)?;
1830
1831 let out_pkt_len = in_pkt.len()
1832 + UdpHeader::SERIALIZED_SIZE
1833 + PspPacket::minimum_packet_size()
1834 + PSP_ICV_SIZE;
1835 let mut pkt_ctx = PktContext::default();
1836 pkt_ctx.psp_cfg.spi = 1;
1837 pkt_ctx.psp_cfg.transport_crypt_off = 1;
1838
1839 let out_pkt = psp_transport_encap(&mut pkt_ctx, &in_pkt)?;
1840 assert_eq!(out_pkt_len, out_pkt.len());
1841
1842 let pkt = PacketHeaders::from_ethernet_slice(&out_pkt)?;
1843 assert!(pkt.link.is_some());
1844 assert_eq!(pkt.link.unwrap().ether_type, EtherType::Ipv4 as u16);
1845 assert!(pkt.ip.is_some());
1846 match pkt.ip.unwrap() {
1847 IpHeader::Version4(ip, _) => {
1848 assert_eq!(ip.source, [192, 168, 1, 1]);
1849 assert_eq!(ip.destination, [192, 168, 1, 2]);
1850 assert_eq!(ip.protocol, IpNumber::Udp as u8);
1851 }
1852 _ => assert!(false),
1853 };
1854 assert!(pkt.transport.is_some());
1855 match pkt.transport.unwrap() {
1856 TransportHeader::Udp(udp) => {
1857 assert_eq!(udp.destination_port, PSP_UDP_PORT);
1858 }
1859 _ => assert!(false),
1860 }
1861 let psp = PspPacket::new(pkt.payload).unwrap();
1862 assert_eq!(psp.get_spi(), pkt_ctx.psp_cfg.spi);
1863 assert_eq!(psp.get_version(), PspVersion::PspVer0 as u8);
1864
1865 Ok(())
1866 }
1867
1868 #[test]
1869 fn check_transport_vc_encap() -> Result<(), Box<dyn std::error::Error>> {
1870 let builder = PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
1871 .ipv4([192, 168, 1, 1], [192, 168, 1, 2], 32)
1872 .udp(21, 1234);
1873 let payload = [1, 2, 3, 4, 5, 6, 7, 8];
1874 let mut in_pkt = Vec::<u8>::with_capacity(builder.size(payload.len()));
1875 builder.write(&mut in_pkt, &payload)?;
1876
1877 let out_pkt_len = in_pkt.len()
1878 + UdpHeader::SERIALIZED_SIZE
1879 + PspPacket::minimum_packet_size()
1880 + PSP_VC_SIZE
1881 + PSP_ICV_SIZE;
1882 let mut pkt_ctx = PktContext::default();
1883 pkt_ctx.psp_cfg.spi = 1;
1884 pkt_ctx.psp_cfg.include_vc = true;
1885 pkt_ctx.vc = 0xCAFE;
1886 pkt_ctx.psp_cfg.transport_crypt_off = 4;
1887
1888 let out_pkt = psp_transport_encap(&mut pkt_ctx, &in_pkt)?;
1889 assert_eq!(out_pkt_len, out_pkt.len());
1890
1891 let pkt = PacketHeaders::from_ethernet_slice(&out_pkt)?;
1892 assert!(pkt.link.is_some());
1893 assert_eq!(pkt.link.unwrap().ether_type, EtherType::Ipv4 as u16);
1894 assert!(pkt.ip.is_some());
1895 match pkt.ip.unwrap() {
1896 IpHeader::Version4(ip, _) => {
1897 assert_eq!(ip.source, [192, 168, 1, 1]);
1898 assert_eq!(ip.destination, [192, 168, 1, 2]);
1899 assert_eq!(ip.protocol, IpNumber::Udp as u8);
1900 }
1901 _ => assert!(false),
1902 };
1903 assert!(pkt.transport.is_some());
1904 match pkt.transport.unwrap() {
1905 TransportHeader::Udp(udp) => {
1906 assert_eq!(udp.destination_port, PSP_UDP_PORT);
1907 }
1908 _ => assert!(false),
1909 }
1910 let psp = PspPacket::new(pkt.payload).unwrap();
1911 assert_eq!(psp.get_spi(), pkt_ctx.psp_cfg.spi);
1912 assert_eq!(psp.get_version(), PspVersion::PspVer0 as u8);
1913 assert_eq!(psp.get_v(), 1);
1914 assert_eq!(psp.get_vc(), vec![0xCAFE]);
1915
1916 Ok(())
1917 }
1918
1919 fn get_pkt_ctx(ver: PspVersion) -> PktContext {
1920 let mut pkt_ctx = PktContext::new();
1921 match ver {
1922 PspVersion::PspVer0 => {
1923 pkt_ctx.psp_cfg.crypto_alg = CryptoAlg::AesGcm128;
1924 pkt_ctx.key = vec![
1925 0x96, 0xc2, 0x2d, 0xc7, 0x99, 0x19, 0x80, 0x90, 0xb7, 0x4b, 0x70, 0xae, 0x46,
1926 0x8e, 0x4e, 0x30,
1927 ];
1928 pkt_ctx.iv = 0x12345678_9ABCDEFF;
1929 pkt_ctx.psp_cfg.spi = 0x12345678;
1930 pkt_ctx.psp_cfg.transport_crypt_off = 1;
1931 pkt_ctx.psp_cfg.ipv4_tunnel_crypt_off = 6;
1932 pkt_ctx.psp_cfg.ipv6_tunnel_crypt_off = 11;
1933 }
1934 PspVersion::PspVer1 => {
1935 pkt_ctx.psp_cfg.crypto_alg = CryptoAlg::AesGcm256;
1936 pkt_ctx.key = vec![
1937 0x96, 0xc2, 0x2d, 0xc7, 0x99, 0x19, 0x80, 0x90, 0xb7, 0x4b, 0x70, 0xae, 0x46,
1938 0x8e, 0x4e, 0x30, 0xab, 0xcd, 0xef, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
1939 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
1940 ];
1941 pkt_ctx.iv = 0x12345678_9ABCDEFF;
1942 pkt_ctx.psp_cfg.spi = 0x82345678;
1943 }
1944 }
1945 pkt_ctx
1946 }
1947
1948 fn get_ipv4_test_pkt() -> Vec<u8> {
1949 let builder = PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
1951 .ipv4([192, 168, 1, 1], [192, 168, 1, 2], 32)
1952 .udp(21, 1234);
1953 let payload = [1, 2, 3, 4, 5, 6, 7, 8];
1954 let mut orig_pkt = Vec::<u8>::with_capacity(builder.size(payload.len()));
1955 builder.write(&mut orig_pkt, &payload).unwrap();
1956 orig_pkt
1957 }
1958
1959 fn get_ipv4_empty_test_pkt() -> Vec<u8> {
1960 let builder = PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
1962 .ipv4([192, 168, 1, 1], [192, 168, 1, 2], 32)
1963 .udp(21, 1234);
1964 let payload = [0u8; 0];
1965 let mut orig_pkt = Vec::<u8>::with_capacity(builder.size(payload.len()));
1966 builder.write(&mut orig_pkt, &payload).unwrap();
1967 orig_pkt
1968 }
1969
1970 fn get_ipv6_test_pkt() -> Vec<u8> {
1971 let builder = PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
1973 .ipv6(
1974 [
1975 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
1976 ],
1977 [
1978 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
1979 ],
1980 32,
1981 )
1982 .udp(21, 1234);
1983 let payload = [1, 2, 3, 4, 5, 6, 7, 8];
1984 let mut orig_pkt = Vec::<u8>::with_capacity(builder.size(payload.len()));
1985 builder.write(&mut orig_pkt, &payload).unwrap();
1986 orig_pkt
1987 }
1988
1989 #[test]
1990 fn test_pspv0_encrypt_decrypt() -> Result<(), Box<dyn std::error::Error>> {
1991 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer0);
1992
1993 let mut psp_hdr = PspHeader::default();
1994 psp_hdr.next_hdr = 6;
1995 psp_hdr.spi = pkt_ctx.psp_cfg.spi;
1996 psp_hdr.iv = pkt_ctx.iv;
1997 let aad = bincode::DefaultOptions::new()
1998 .with_fixint_encoding()
1999 .with_big_endian()
2000 .serialize(&psp_hdr)?;
2001
2002 pkt_ctx.key = derive_psp_key(
2003 pkt_ctx.psp_cfg.spi,
2004 pkt_ctx.psp_cfg.crypto_alg,
2005 &pkt_ctx.psp_cfg.master_keys,
2006 );
2007 let gcm_iv = get_aesgcm_iv(pkt_ctx.psp_cfg.spi, pkt_ctx.iv);
2008
2009 let cleartext = vec![0u8; 256];
2010 let mut ciphertext = vec![0u8; cleartext.len() + PSP_ICV_SIZE];
2011
2012 let rc = psp_encrypt(
2013 pkt_ctx.psp_cfg.crypto_alg,
2014 &pkt_ctx.key,
2015 &gcm_iv,
2016 &aad,
2017 &cleartext,
2018 &mut ciphertext,
2019 );
2020 assert!(rc.is_ok());
2021 let mut decrypted = vec![1u8; cleartext.len()];
2022 let rc = psp_decrypt(
2023 pkt_ctx.psp_cfg.crypto_alg,
2024 &pkt_ctx.key,
2025 &gcm_iv,
2026 &aad,
2027 &ciphertext,
2028 &mut decrypted,
2029 );
2030 assert!(rc.is_ok());
2031 assert_eq!(cleartext.len(), decrypted.len());
2032 assert_eq!(cleartext, decrypted);
2033
2034 Ok(())
2035 }
2036
2037 #[test]
2038 fn test_pspv1_encrypt_decrypt() -> Result<(), Box<dyn std::error::Error>> {
2039 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer1);
2040
2041 let mut psp_hdr = PspHeader::default();
2042 psp_hdr.next_hdr = 6;
2043 psp_hdr.spi = pkt_ctx.psp_cfg.spi;
2044 psp_hdr.iv = pkt_ctx.iv;
2045 let aad = bincode::DefaultOptions::new()
2046 .with_fixint_encoding()
2047 .with_big_endian()
2048 .serialize(&psp_hdr)?;
2049
2050 pkt_ctx.key = derive_psp_key(
2051 pkt_ctx.psp_cfg.spi,
2052 pkt_ctx.psp_cfg.crypto_alg,
2053 &pkt_ctx.psp_cfg.master_keys,
2054 );
2055 let gcm_iv = get_aesgcm_iv(pkt_ctx.psp_cfg.spi, pkt_ctx.iv);
2056
2057 let cleartext = vec![0u8; 256];
2058 let mut ciphertext = vec![0u8; cleartext.len() + PSP_ICV_SIZE];
2059
2060 let rc = psp_encrypt(
2061 pkt_ctx.psp_cfg.crypto_alg,
2062 &pkt_ctx.key,
2063 &gcm_iv,
2064 &aad,
2065 &cleartext,
2066 &mut ciphertext,
2067 );
2068 assert!(rc.is_ok());
2069 let mut decrypted = vec![1u8; cleartext.len()];
2070 let rc = psp_decrypt(
2071 pkt_ctx.psp_cfg.crypto_alg,
2072 &pkt_ctx.key,
2073 &gcm_iv,
2074 &aad,
2075 &ciphertext,
2076 &mut decrypted,
2077 );
2078 assert!(rc.is_ok());
2079 assert_eq!(cleartext.len(), decrypted.len());
2080 assert_eq!(cleartext, decrypted);
2081
2082 Ok(())
2083 }
2084
2085 #[test_log::test]
2086 fn test_pspv0_transport_encap_decap_ipv4() -> Result<(), PspError> {
2087 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer0);
2088 let mut decap_pkt_ctx = pkt_ctx.clone();
2089 let orig_pkt = get_ipv4_test_pkt();
2090
2091 pkt_ctx.key = derive_psp_key(
2092 pkt_ctx.psp_cfg.spi,
2093 pkt_ctx.psp_cfg.crypto_alg,
2094 &pkt_ctx.psp_cfg.master_keys,
2095 );
2096
2097 let encap_pkt = psp_transport_encap(&mut pkt_ctx, &orig_pkt)?;
2098 let decap_pkt = psp_transport_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2099 assert_eq!(orig_pkt, decap_pkt);
2100
2101 Ok(())
2102 }
2103
2104 #[test_log::test]
2105 fn test_pspv0_transport_encap_decap_crypt_off() -> Result<(), PspError> {
2106 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer0);
2107 pkt_ctx.psp_cfg.transport_crypt_off = 1;
2108 let mut decap_pkt_ctx = pkt_ctx.clone();
2109 let orig_pkt = get_ipv4_test_pkt();
2110
2111 pkt_ctx.key = derive_psp_key(
2112 pkt_ctx.psp_cfg.spi,
2113 pkt_ctx.psp_cfg.crypto_alg,
2114 &pkt_ctx.psp_cfg.master_keys,
2115 );
2116
2117 let encap_pkt = psp_transport_encap(&mut pkt_ctx, &orig_pkt)?;
2118 let decap_pkt = psp_transport_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2119 assert_eq!(orig_pkt, decap_pkt);
2120
2121 Ok(())
2122 }
2123
2124 #[test_log::test]
2125 fn test_pspv1_transport_encap_decap_ipv4() -> Result<(), PspError> {
2126 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer1);
2127 let mut decap_pkt_ctx = pkt_ctx.clone();
2128 let orig_pkt = get_ipv4_test_pkt();
2129
2130 pkt_ctx.key = derive_psp_key(
2131 pkt_ctx.psp_cfg.spi,
2132 pkt_ctx.psp_cfg.crypto_alg,
2133 &pkt_ctx.psp_cfg.master_keys,
2134 );
2135
2136 let encap_pkt = psp_transport_encap(&mut pkt_ctx, &orig_pkt)?;
2137 let decap_pkt = psp_transport_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2138 assert_eq!(orig_pkt, decap_pkt);
2139
2140 Ok(())
2141 }
2142
2143 #[test_log::test]
2144 fn test_pspv0_transport_encap_decap_ipv6() -> Result<(), PspError> {
2145 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer0);
2146 let mut decap_pkt_ctx = pkt_ctx.clone();
2147 let orig_pkt = get_ipv6_test_pkt();
2148
2149 pkt_ctx.key = derive_psp_key(
2150 pkt_ctx.psp_cfg.spi,
2151 pkt_ctx.psp_cfg.crypto_alg,
2152 &pkt_ctx.psp_cfg.master_keys,
2153 );
2154
2155 let encap_pkt = psp_transport_encap(&mut pkt_ctx, &orig_pkt)?;
2156 let decap_pkt = psp_transport_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2157 assert_eq!(orig_pkt, decap_pkt);
2158
2159 Ok(())
2160 }
2161
2162 #[test_log::test]
2163 fn test_pspv1_transport_encap_decap_ipv6() -> Result<(), PspError> {
2164 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer1);
2165 let mut decap_pkt_ctx = pkt_ctx.clone();
2166 let orig_pkt = get_ipv6_test_pkt();
2167
2168 pkt_ctx.key = derive_psp_key(
2169 pkt_ctx.psp_cfg.spi,
2170 pkt_ctx.psp_cfg.crypto_alg,
2171 &pkt_ctx.psp_cfg.master_keys,
2172 );
2173
2174 let encap_pkt = psp_transport_encap(&mut pkt_ctx, &orig_pkt)?;
2175 let decap_pkt = psp_transport_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2176 assert_eq!(orig_pkt, decap_pkt);
2177
2178 Ok(())
2179 }
2180
2181 #[test_log::test]
2182 fn test_pspv0_tunnel_encap_decap_ipv4() -> Result<(), PspError> {
2183 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer0);
2184 let mut decap_pkt_ctx = pkt_ctx.clone();
2185 let orig_pkt = get_ipv4_test_pkt();
2186
2187 pkt_ctx.key = derive_psp_key(
2188 pkt_ctx.psp_cfg.spi,
2189 pkt_ctx.psp_cfg.crypto_alg,
2190 &pkt_ctx.psp_cfg.master_keys,
2191 );
2192
2193 let encap_pkt = psp_tunnel_encap(&mut pkt_ctx, &orig_pkt)?;
2194 let decap_pkt = psp_tunnel_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2195 assert_eq!(orig_pkt, decap_pkt);
2196
2197 Ok(())
2198 }
2199
2200 #[test_log::test]
2201 fn test_pspv0_tunnel_encap_decap_crypt_off() -> Result<(), PspError> {
2202 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer0);
2203 pkt_ctx.psp_cfg.ipv4_tunnel_crypt_off = 2;
2204 let mut decap_pkt_ctx = pkt_ctx.clone();
2205 let orig_pkt = get_ipv4_test_pkt();
2206
2207 pkt_ctx.key = derive_psp_key(
2208 pkt_ctx.psp_cfg.spi,
2209 pkt_ctx.psp_cfg.crypto_alg,
2210 &pkt_ctx.psp_cfg.master_keys,
2211 );
2212
2213 let encap_pkt = psp_tunnel_encap(&mut pkt_ctx, &orig_pkt)?;
2214 let decap_pkt = psp_tunnel_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2215 assert_eq!(orig_pkt, decap_pkt);
2216
2217 Ok(())
2218 }
2219
2220 #[test_log::test]
2221 fn test_pspv1_tunnel_encap_decap_ipv4() -> Result<(), PspError> {
2222 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer1);
2223 let mut decap_pkt_ctx = pkt_ctx.clone();
2224 let orig_pkt = get_ipv4_test_pkt();
2225
2226 pkt_ctx.key = derive_psp_key(
2227 pkt_ctx.psp_cfg.spi,
2228 pkt_ctx.psp_cfg.crypto_alg,
2229 &pkt_ctx.psp_cfg.master_keys,
2230 );
2231
2232 let encap_pkt = psp_tunnel_encap(&mut pkt_ctx, &orig_pkt)?;
2233 let decap_pkt = psp_tunnel_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2234 assert_eq!(orig_pkt, decap_pkt);
2235
2236 Ok(())
2237 }
2238
2239 #[test_log::test]
2240 fn test_pspv0_tunnel_encap_decap_ipv6() -> Result<(), PspError> {
2241 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer0);
2242 let mut decap_pkt_ctx = pkt_ctx.clone();
2243 let orig_pkt = get_ipv6_test_pkt();
2244
2245 pkt_ctx.key = derive_psp_key(
2246 pkt_ctx.psp_cfg.spi,
2247 pkt_ctx.psp_cfg.crypto_alg,
2248 &pkt_ctx.psp_cfg.master_keys,
2249 );
2250
2251 let encap_pkt = psp_tunnel_encap(&mut pkt_ctx, &orig_pkt)?;
2252 let decap_pkt = psp_tunnel_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2253 assert_eq!(orig_pkt, decap_pkt);
2254
2255 Ok(())
2256 }
2257
2258 #[test_log::test]
2259 fn test_pspv1_tunnel_encap_decap_ipv6() -> Result<(), PspError> {
2260 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer1);
2261 let mut decap_pkt_ctx = pkt_ctx.clone();
2262 let orig_pkt = get_ipv6_test_pkt();
2263
2264 pkt_ctx.key = derive_psp_key(
2265 pkt_ctx.psp_cfg.spi,
2266 pkt_ctx.psp_cfg.crypto_alg,
2267 &pkt_ctx.psp_cfg.master_keys,
2268 );
2269
2270 let encap_pkt = psp_tunnel_encap(&mut pkt_ctx, &orig_pkt)?;
2271 let decap_pkt = psp_tunnel_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2272 assert_eq!(orig_pkt, decap_pkt);
2273
2274 Ok(())
2275 }
2276
2277 #[test_log::test]
2278 fn test_tunnel_encap_decap_ipv6_vc() -> Result<(), PspError> {
2279 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer0);
2280 pkt_ctx.psp_cfg.include_vc = true;
2281 let mut decap_pkt_ctx = pkt_ctx.clone();
2282 let orig_pkt = get_ipv6_test_pkt();
2283
2284 pkt_ctx.key = derive_psp_key(
2285 pkt_ctx.psp_cfg.spi,
2286 pkt_ctx.psp_cfg.crypto_alg,
2287 &pkt_ctx.psp_cfg.master_keys,
2288 );
2289
2290 let encap_pkt = psp_tunnel_encap(&mut pkt_ctx, &orig_pkt)?;
2291 let decap_pkt = psp_tunnel_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2292 assert_eq!(orig_pkt, decap_pkt);
2293
2294 Ok(())
2295 }
2296
2297 #[test_log::test]
2298 fn test_tunnel_encap_decap_ipv6_vc_no_co() -> Result<(), PspError> {
2299 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer0);
2300 pkt_ctx.psp_cfg.include_vc = true;
2301 pkt_ctx.psp_cfg.ipv6_tunnel_crypt_off = 0;
2302 let mut decap_pkt_ctx = pkt_ctx.clone();
2303 let orig_pkt = get_ipv6_test_pkt();
2304
2305 pkt_ctx.key = derive_psp_key(
2306 pkt_ctx.psp_cfg.spi,
2307 pkt_ctx.psp_cfg.crypto_alg,
2308 &pkt_ctx.psp_cfg.master_keys,
2309 );
2310
2311 let encap_pkt = psp_tunnel_encap(&mut pkt_ctx, &orig_pkt)?;
2312 let decap_pkt = psp_tunnel_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2313 assert_eq!(orig_pkt, decap_pkt);
2314
2315 Ok(())
2316 }
2317
2318 #[test_log::test]
2319 fn test_tunnel_encap_decap_ipv6_vc_partial_enc() -> Result<(), PspError> {
2320 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer0);
2321 pkt_ctx.psp_cfg.include_vc = true;
2322 pkt_ctx.psp_cfg.ipv6_tunnel_crypt_off = 1;
2323 let mut decap_pkt_ctx = pkt_ctx.clone();
2324 let orig_pkt = get_ipv6_test_pkt();
2325
2326 pkt_ctx.key = derive_psp_key(
2327 pkt_ctx.psp_cfg.spi,
2328 pkt_ctx.psp_cfg.crypto_alg,
2329 &pkt_ctx.psp_cfg.master_keys,
2330 );
2331
2332 let encap_pkt = psp_tunnel_encap(&mut pkt_ctx, &orig_pkt)?;
2333 let decap_pkt = psp_tunnel_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2334 assert_eq!(orig_pkt, decap_pkt);
2335
2336 Ok(())
2337 }
2338
2339 #[test_log::test]
2340 fn test_pspv1_transport_ipv4_empty() -> Result<(), PspError> {
2341 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer1);
2342 let mut decap_pkt_ctx = pkt_ctx.clone();
2343 let orig_pkt = get_ipv4_empty_test_pkt();
2344
2345 pkt_ctx.key = derive_psp_key(
2346 pkt_ctx.psp_cfg.spi,
2347 pkt_ctx.psp_cfg.crypto_alg,
2348 &pkt_ctx.psp_cfg.master_keys,
2349 );
2350
2351 let encap_pkt = psp_transport_encap(&mut pkt_ctx, &orig_pkt)?;
2352 let decap_pkt = psp_transport_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2353 assert_eq!(orig_pkt, decap_pkt);
2354
2355 Ok(())
2356 }
2357
2358 #[test_log::test]
2359 fn test_pspv1_tunnel_ipv4_empty() -> Result<(), PspError> {
2360 let mut pkt_ctx = get_pkt_ctx(PspVersion::PspVer1);
2361 let mut decap_pkt_ctx = pkt_ctx.clone();
2362 let orig_pkt = get_ipv4_empty_test_pkt();
2363
2364 pkt_ctx.key = derive_psp_key(
2365 pkt_ctx.psp_cfg.spi,
2366 pkt_ctx.psp_cfg.crypto_alg,
2367 &pkt_ctx.psp_cfg.master_keys,
2368 );
2369
2370 let encap_pkt = psp_tunnel_encap(&mut pkt_ctx, &orig_pkt)?;
2371 let decap_pkt = psp_tunnel_decap(&mut decap_pkt_ctx, &encap_pkt)?;
2372 assert_eq!(orig_pkt, decap_pkt);
2373
2374 Ok(())
2375 }
2376
2377 mod security_tests {
2379 use super::*;
2380
2381 #[test]
2382 fn test_no_zero_keys_in_new_context() {
2383 let ctx = PktContext::new();
2384
2385 assert!(
2387 !ctx.psp_cfg.master_keys[0].iter().all(|&b| b == 0),
2388 "Master key 0 should not be all zeros"
2389 );
2390 assert!(
2391 !ctx.psp_cfg.master_keys[1].iter().all(|&b| b == 0),
2392 "Master key 1 should not be all zeros"
2393 );
2394
2395 assert!(
2397 !ctx.key.iter().all(|&b| b == 0),
2398 "Derived key should not be all zeros"
2399 );
2400
2401 assert_ne!(ctx.iv, 1, "IV should not be predictable value 1");
2403 assert_ne!(ctx.iv, 0, "IV should not be zero");
2404 }
2405
2406 #[test]
2407 fn test_secure_spi_generation() {
2408 let spi1 = PktContext::generate_secure_spi();
2409 let spi2 = PktContext::generate_secure_spi();
2410
2411 assert_ne!(spi1, 0, "SPI should not be 0");
2413 assert_ne!(spi1, 1, "SPI should not be 1");
2414 assert_ne!(spi2, 0, "SPI should not be 0");
2415 assert_ne!(spi2, 1, "SPI should not be 1");
2416
2417 assert_ne!(spi1, spi2, "Generated SPIs should be different");
2419 }
2420
2421 #[test]
2422 fn test_config_validation_rejects_zero_keys() {
2423 let mut cfg = PspConfig::default();
2424
2425 cfg.master_keys[0] = [0u8; 32];
2427 cfg.master_keys[1] = [0u8; 32];
2428 cfg.spi = 123; assert!(
2432 cfg.validate().is_err(),
2433 "Validation should reject all-zero keys"
2434 );
2435 }
2436
2437 #[test]
2438 fn test_config_validation_rejects_repeating_patterns() {
2439 let mut cfg = PspConfig::default();
2440
2441 cfg.master_keys[0] = [0xAA; 32];
2443 cfg.master_keys[1] = [0x11; 32];
2444 cfg.spi = 123; assert!(
2448 cfg.validate().is_err(),
2449 "Validation should reject repeating key patterns"
2450 );
2451 }
2452
2453 #[test]
2454 fn test_config_validation_rejects_zero_spi() {
2455 let mut cfg = PspConfig::default();
2456
2457 cfg.master_keys[0] = PktContext::generate_secure_key();
2459 cfg.master_keys[1] = PktContext::generate_secure_key();
2460 cfg.spi = 0; assert!(
2464 cfg.validate().is_err(),
2465 "Validation should reject SPI value of 0"
2466 );
2467 }
2468
2469 #[test]
2470 fn test_config_validation_rejects_large_crypto_offsets() {
2471 let mut cfg = PspConfig::default();
2472
2473 cfg.master_keys[0] = PktContext::generate_secure_key();
2475 cfg.master_keys[1] = PktContext::generate_secure_key();
2476 cfg.spi = 123;
2477
2478 cfg.transport_crypt_off = 65; assert!(
2481 cfg.validate().is_err(),
2482 "Validation should reject large transport crypto offset"
2483 );
2484
2485 cfg.transport_crypt_off = 0; cfg.ipv4_tunnel_crypt_off = 65; assert!(
2488 cfg.validate().is_err(),
2489 "Validation should reject large IPv4 tunnel crypto offset"
2490 );
2491
2492 cfg.ipv4_tunnel_crypt_off = 0; cfg.ipv6_tunnel_crypt_off = 65; assert!(
2495 cfg.validate().is_err(),
2496 "Validation should reject large IPv6 tunnel crypto offset"
2497 );
2498 }
2499
2500 #[test]
2501 fn test_secure_config_passes_validation() {
2502 let cfg = PspConfig::new_secure().expect("Should create secure config");
2504
2505 assert!(
2507 cfg.validate().is_ok(),
2508 "Secure configuration should pass validation"
2509 );
2510
2511 assert_eq!(cfg.crypto_alg, CryptoAlg::AesGcm256, "Should default to AES-GCM-256");
2513 }
2514
2515 #[test]
2516 fn test_key_uniqueness() {
2517 let key1 = PktContext::generate_secure_key();
2518 let key2 = PktContext::generate_secure_key();
2519
2520 assert_ne!(key1, key2, "Generated keys should be unique");
2522
2523 assert!(!key1.iter().all(|&b| b == key1[0]), "Key should not be all same byte");
2525 assert!(!key2.iter().all(|&b| b == key2[0]), "Key should not be all same byte");
2526 }
2527
2528 #[test]
2529 fn test_testing_context_has_predictable_values() {
2530 let ctx = PktContext::new_for_testing();
2531
2532 assert_eq!(ctx.psp_cfg.master_keys[0], [0u8; 32], "Test key 0 should be all zeros");
2534 assert_eq!(ctx.psp_cfg.master_keys[1], [0u8; 32], "Test key 1 should be all zeros");
2535 assert_eq!(ctx.psp_cfg.spi, 1, "Test SPI should be 1");
2536 assert_eq!(ctx.iv, 1, "Test IV should be 1");
2537 }
2538 }
2539}