byte_array_ops/core/trust/insecure/
vec.rs

1//! Vec-like operations and conversions for ByteArray in insecure mode
2//!
3//! Provides Deref to `Vec<u8>`, ownership transfer, and truncation
4
5use crate::core::model::ByteArray;
6use alloc::vec::Vec;
7use core::ops::Deref;
8
9impl From<ByteArray> for Vec<u8> {
10    /// This conversion and ownership transfer is only available in non-hardened modes
11    fn from(arr: ByteArray) -> Self {
12        arr.bytes // Zero-cost move
13    }
14}
15
16impl ByteArray {
17    /// This transforms the bytearray into an owned vector an is thus unavailable in hardned modes
18    /// Allowing this in hardened modes means giving over control of resource sanitization to user
19    /// which would not guarantee a proper purge TODO add security handbook readme
20    pub fn to_vec(self) -> Vec<u8> {
21        self.into()
22    }
23
24    /// truncate function similar to [`Vec::truncate`]. This is the insecure implementation
25    /// TODO move this as part of the SecureReallocationProvider trait which collects all common
26    /// vector methods that might cause reallocation
27    pub fn truncate(&mut self, len: usize) {
28        self.bytes.truncate(len)
29    }
30}
31
32impl Deref for ByteArray {
33    type Target = Vec<u8>;
34
35    /// This exposes the underlying `Vec<u8>` type. It is unavailable in hardened modes
36    /// due to the fact that it exposes functions that transfer ownership thus increasing the risk
37    /// of inadvertent improper sanitization of sensitive data.
38    fn deref(&self) -> &Self::Target {
39        &self.bytes
40    }
41}
42
43#[cfg(test)]
44mod tests_non_hardened_only {
45    use super::*;
46    use alloc::vec;
47    use alloc::vec::Vec;
48
49    #[test]
50    fn test_deref_access_vec_methods() {
51        let arr: ByteArray = vec![0x01, 0x02, 0x03, 0x04].into();
52
53        // Access Vec methods through Deref
54        assert_eq!((*arr).len(), 4);
55        assert!(!arr.is_empty());
56        assert_eq!(arr.capacity(), arr.bytes.capacity());
57    }
58
59    #[test]
60    fn test_deref_indexing() {
61        let arr: ByteArray = vec![0xaa, 0xbb, 0xcc].into();
62
63        // Index through Deref
64        assert_eq!(arr[0], 0xaa);
65        assert_eq!(arr[1], 0xbb);
66        assert_eq!(arr[2], 0xcc);
67    }
68
69    #[test]
70    fn test_deref_iteration() {
71        let arr: ByteArray = vec![0x01, 0x02, 0x03].into();
72
73        // Iterate through Deref
74        let collected: Vec<u8> = arr.iter().copied().collect();
75        assert_eq!(collected, vec![0x01, 0x02, 0x03]);
76    }
77
78    #[test]
79    fn test_deref_get() {
80        let arr: ByteArray = vec![0xde, 0xad, 0xbe, 0xef].into();
81
82        // Access get() through Deref
83        assert_eq!(arr.get(0), Some(&0xde));
84        assert_eq!(arr.get(3), Some(&0xef));
85        assert_eq!(arr.get(4), None);
86    }
87
88    #[test]
89    fn test_deref_first_last() {
90        let arr: ByteArray = vec![0x11, 0x22, 0x33].into();
91
92        // Access first() and last() through Deref
93        assert_eq!(arr.first(), Some(&0x11));
94        assert_eq!(arr.last(), Some(&0x33));
95
96        let empty = ByteArray::default();
97        assert_eq!(empty.first(), None);
98        assert_eq!(empty.last(), None);
99    }
100
101    #[test]
102    fn test_deref_slice_methods() {
103        let arr: ByteArray = vec![0xaa, 0xbb, 0xcc, 0xdd].into();
104
105        // Access slice methods through Deref
106        assert!(arr.starts_with(&[0xaa, 0xbb]));
107        assert!(arr.ends_with(&[0xcc, 0xdd]));
108        assert!(arr.contains(&0xcc));
109        assert!(!arr.contains(&0xff));
110    }
111    #[test]
112    fn test_roundtrip_vec() {
113        let original = vec![0x01, 0x02, 0x03, 0x04];
114        let arr = ByteArray::from(original.clone());
115        let extracted: Vec<u8> = arr.clone().into();
116        let extracted_through_method = arr.to_vec();
117
118        assert_eq!(original, extracted);
119        assert_eq!(original, extracted_through_method)
120    }
121    #[test]
122    fn test_into_vec() {
123        let arr: ByteArray = vec![0xde, 0xad, 0xbe, 0xef].into();
124
125        let extracted: Vec<u8> = arr.clone().into();
126        let extracted_via_method = arr.to_vec();
127
128        assert_eq!(extracted, vec![0xde, 0xad, 0xbe, 0xef]);
129        assert_eq!(extracted_via_method, extracted)
130    }
131
132    #[test]
133    fn test_into_vec_empty() {
134        let arr = ByteArray::default();
135
136        let extracted: Vec<u8> = arr.clone().into();
137
138        let extracted_via_method = arr.to_vec();
139
140        assert!(extracted.is_empty());
141        assert!(extracted_via_method.is_empty());
142    }
143
144    #[test]
145    fn test_truncate_to_smaller_length() {
146        let mut arr: ByteArray = vec![0x01, 0x02, 0x03, 0x04, 0x05].into();
147        arr.truncate(3);
148
149        assert_eq!(arr.len(), 3);
150        assert_eq!(arr.as_bytes(), [0x01, 0x02, 0x03]);
151    }
152
153    #[test]
154    fn test_truncate_to_zero() {
155        let mut arr: ByteArray = vec![0xaa, 0xbb, 0xcc].into();
156        arr.truncate(0);
157
158        assert_eq!(arr.len(), 0);
159        assert!(arr.is_empty());
160    }
161
162    #[test]
163    fn test_truncate_to_same_length() {
164        let mut arr: ByteArray = vec![0x01, 0x02, 0x03].into();
165        arr.truncate(3);
166
167        assert_eq!(arr.len(), 3);
168        assert_eq!(arr.as_bytes(), [0x01, 0x02, 0x03]);
169    }
170
171    #[test]
172    fn test_truncate_to_larger_length() {
173        let mut arr: ByteArray = vec![0x01, 0x02].into();
174        arr.truncate(10);
175
176        // Should have no effect when truncating to larger size
177        assert_eq!(arr.len(), 2);
178        assert_eq!(arr.as_bytes(), [0x01, 0x02]);
179    }
180
181    #[test]
182    fn test_truncate_empty_array() {
183        let mut arr = ByteArray::default();
184        arr.truncate(0);
185
186        assert!(arr.is_empty());
187    }
188
189    #[test]
190    fn test_truncate_single_byte() {
191        let mut arr: ByteArray = vec![0xff, 0xee, 0xdd].into();
192        arr.truncate(1);
193
194        assert_eq!(arr.len(), 1);
195        assert_eq!(arr.as_bytes(), [0xff]);
196    }
197}