libsodium_rs/utils/mod.rs
1//! # Cryptographic Utilities
2//!
3//! This module provides various utility functions for cryptographic operations, including
4//! secure memory management, constant-time comparisons, and encoding/decoding functions.
5//! These utilities are designed to help implement cryptographic protocols securely and
6//! efficiently.
7//!
8//! ## Security Considerations
9//!
10//! - Many functions in this module are specifically designed to prevent side-channel attacks
11//! and other security vulnerabilities.
12//! - The memory management functions help prevent sensitive data from being leaked or
13//! swapped to disk.
14//! - Always use these utilities when handling sensitive cryptographic material.
15//!
16//! ## Key Features
17//!
18//! - **Secure Memory Management**: Functions for securely allocating, protecting, and
19//! clearing memory containing sensitive data.
20//! - **Constant-Time Operations**: Functions for comparing data in constant time to prevent
21//! timing attacks.
22//! - **Encoding/Decoding**: Functions for converting between binary data and hexadecimal or
23//! Base64 representations.
24//! - **Arithmetic Operations**: Functions for performing arithmetic on big-endian encoded
25//! numbers, useful for nonce management.
26//!
27//! ## Example
28//!
29//! ```rust
30//! use libsodium_rs as sodium;
31//! use sodium::utils;
32//! use sodium::ensure_init;
33//!
34//! fn main() -> Result<(), Box<dyn std::error::Error>> {
35//! ensure_init()?;
36//!
37//! // Secure memory operations
38//! let mut sensitive_data = [0x01, 0x02, 0x03, 0x04];
39//!
40//! // Lock memory to prevent it from being swapped to disk
41//! utils::mlock(&mut sensitive_data).expect("Failed to lock memory");
42//!
43//! // Use the sensitive data...
44//!
45//! // Securely zero the memory when done
46//! utils::memzero(&mut sensitive_data);
47//! assert_eq!(sensitive_data, [0, 0, 0, 0]);
48//!
49//! // Unlock the memory
50//! utils::munlock(&mut sensitive_data).expect("Failed to unlock memory");
51//!
52//! // Constant-time comparison
53//! let tag1 = [0x01, 0x02, 0x03, 0x04];
54//! let tag2 = [0x01, 0x02, 0x03, 0x04];
55//! assert!(utils::memcmp(&tag1, &tag2));
56//!
57//! // Encoding/decoding
58//! let binary = [0xDE, 0xAD, 0xBE, 0xEF];
59//! let hex = utils::bin2hex(&binary);
60//! assert_eq!(hex, "deadbeef");
61//!
62//! Ok(())
63//! }
64//! ```
65//!
66
67use crate::Result;
68use libsodium_sys;
69
70/// Base64 encoding variant: original (standard) Base64 encoding
71pub const BASE64_VARIANT_ORIGINAL: i32 = libsodium_sys::sodium_base64_VARIANT_ORIGINAL as i32;
72
73/// Base64 encoding variant: original (standard) Base64 encoding without padding
74pub const BASE64_VARIANT_ORIGINAL_NO_PADDING: i32 =
75 libsodium_sys::sodium_base64_VARIANT_ORIGINAL_NO_PADDING as i32;
76
77/// Base64 encoding variant: URL-safe Base64 encoding
78pub const BASE64_VARIANT_URLSAFE: i32 = libsodium_sys::sodium_base64_VARIANT_URLSAFE as i32;
79
80/// Base64 encoding variant: URL-safe Base64 encoding without padding
81pub const BASE64_VARIANT_URLSAFE_NO_PADDING: i32 =
82 libsodium_sys::sodium_base64_VARIANT_URLSAFE_NO_PADDING as i32;
83
84/// Compare two byte slices in constant time
85///
86/// This function compares two byte slices in constant time, which is important for
87/// comparing secret data like authentication tags or passwords. It returns true if
88/// the slices are equal, false otherwise.
89///
90/// ## Security Considerations
91///
92/// - This function is designed to prevent timing attacks that could leak information
93/// about the contents of the slices being compared.
94/// - It should be used whenever comparing sensitive data like authentication tags,
95/// MACs, or password hashes.
96/// - Regular comparison operators (==) should NOT be used for comparing secret data
97/// as they may be vulnerable to timing attacks.
98///
99/// ## Example
100///
101/// ```rust
102/// use libsodium_rs as sodium;
103/// use sodium::utils;
104///
105/// let tag1 = [0x01, 0x02, 0x03, 0x04];
106/// let tag2 = [0x01, 0x02, 0x03, 0x04];
107/// let tag3 = [0x01, 0x02, 0x03, 0x05];
108///
109/// // Compare in constant time
110/// assert!(utils::memcmp(&tag1, &tag2)); // Equal
111/// assert!(!utils::memcmp(&tag1, &tag3)); // Not equal
112/// ```
113///
114/// # Arguments
115/// * `a` - First byte slice to compare
116/// * `b` - Second byte slice to compare
117///
118/// # Returns
119/// * `bool` - `true` if the slices are equal, `false` otherwise
120pub fn memcmp(a: &[u8], b: &[u8]) -> bool {
121 if a.len() != b.len() {
122 return false;
123 }
124
125 unsafe {
126 libsodium_sys::sodium_memcmp(a.as_ptr() as *const _, b.as_ptr() as *const _, a.len()) == 0
127 }
128}
129
130/// Zero a byte slice in a way that won't be optimized out
131///
132/// This function securely zeroes a byte slice, ensuring that the operation
133/// won't be optimized out by the compiler. This is important for securely
134/// clearing sensitive data from memory.
135///
136/// ## Security Considerations
137///
138/// - This function ensures that the memory is actually zeroed, even if the compiler
139/// would normally optimize out the operation
140/// - It should be used whenever a byte slice containing sensitive data (like cryptographic
141/// keys or passwords) is no longer needed
142/// - Regular assignment (e.g., `slice = [0; len]`) might be optimized out by the
143/// compiler and not actually clear the memory
144///
145/// ## Example
146///
147/// ```rust
148/// use libsodium_rs as sodium;
149/// use sodium::utils;
150///
151/// // Create a slice with sensitive data
152/// let mut secret_key = [0x01, 0x02, 0x03, 0x04];
153///
154/// // Use the key for some operation...
155///
156/// // Securely clear the key from memory when done
157/// utils::memzero(&mut secret_key);
158/// assert_eq!(secret_key, [0, 0, 0, 0]);
159/// ```
160///
161/// # Arguments
162/// * `buf` - The byte slice to zero
163pub fn memzero(buf: &mut [u8]) {
164 unsafe {
165 libsodium_sys::sodium_memzero(buf.as_mut_ptr() as *mut _, buf.len());
166 }
167}
168
169/// Zero a region of the stack in a way that won't be optimized out
170///
171/// This function securely zeroes a region of the stack, ensuring that the operation
172/// won't be optimized out by the compiler. This is useful for clearing sensitive
173/// data from the stack before returning from a function.
174///
175/// ## Security Considerations
176///
177/// - This function ensures that the stack memory is actually zeroed, even if the compiler
178/// would normally optimize out the operation
179/// - It should be used when sensitive data is stored on the stack and needs to be cleared
180/// before returning from a function
181///
182/// ## Example
183///
184/// ```rust
185/// use libsodium_rs as sodium;
186/// use sodium::utils;
187///
188/// fn process_sensitive_data() {
189/// // Create sensitive data on the stack
190/// let sensitive_data = [0x01, 0x02, 0x03, 0x04];
191///
192/// // Use the data for some operation...
193///
194/// // Securely clear the data from the stack
195/// utils::stackzero(sensitive_data.len());
196/// }
197/// ```
198///
199/// # Arguments
200/// * `len` - The number of bytes to zero on the stack
201pub fn stackzero(len: usize) {
202 unsafe {
203 libsodium_sys::sodium_stackzero(len);
204 }
205}
206
207/// Lock memory pages containing this slice, preventing them from being swapped to disk
208///
209/// This function locks the memory pages containing the provided byte slice, preventing
210/// them from being swapped to disk. This is important for protecting sensitive
211/// cryptographic material from being written to disk where it might be recovered later.
212///
213/// ## Security Considerations
214///
215/// - Locked memory is not swapped to disk, reducing the risk of sensitive data leakage
216/// - This function should be used for byte slices containing highly sensitive data like
217/// cryptographic keys or passwords
218/// - Remember to call `munlock` when the byte slice is no longer needed
219/// - There may be system-wide limits on the amount of memory that can be locked
220///
221/// ## Example
222///
223/// ```rust
224/// use libsodium_rs as sodium;
225/// use sodium::utils;
226///
227/// let mut sensitive_data = [0x01, 0x02, 0x03, 0x04];
228/// utils::mlock(&mut sensitive_data).expect("Failed to lock memory");
229/// // Use the sensitive data...
230/// utils::munlock(&mut sensitive_data).expect("Failed to unlock memory");
231/// ```
232pub fn mlock(buf: &mut [u8]) -> std::io::Result<()> {
233 let result = unsafe { libsodium_sys::sodium_mlock(buf.as_mut_ptr() as *mut _, buf.len()) };
234
235 if result == 0 {
236 Ok(())
237 } else {
238 Err(std::io::Error::last_os_error())
239 }
240}
241
242/// Unlock previously locked memory pages
243///
244/// This function unlocks memory pages that were previously locked with `mlock`.
245/// It should be called when the sensitive data is no longer needed.
246///
247/// # Returns
248///
249/// * `io::Result<()>` - Success or an error if the memory couldn't be unlocked
250///
251/// ## Example
252///
253/// ```rust
254/// use libsodium_rs as sodium;
255/// use sodium::utils;
256///
257/// let mut sensitive_data = [0x01, 0x02, 0x03, 0x04];
258/// utils::mlock(&mut sensitive_data).expect("Failed to lock memory");
259/// // Use the sensitive data...
260/// utils::munlock(&mut sensitive_data).expect("Failed to unlock memory");
261/// ```
262pub fn munlock(buf: &mut [u8]) -> std::io::Result<()> {
263 let result = unsafe { libsodium_sys::sodium_munlock(buf.as_mut_ptr() as *mut _, buf.len()) };
264
265 if result == 0 {
266 Ok(())
267 } else {
268 Err(std::io::Error::last_os_error())
269 }
270}
271
272/// Increment a number (usually a nonce) stored as big-endian bytes
273pub fn increment_be(n: &mut [u8]) {
274 unsafe {
275 libsodium_sys::sodium_increment(n.as_mut_ptr(), n.len());
276 }
277}
278
279/// Add two numbers stored as big-endian bytes
280///
281/// This function adds two numbers stored as big-endian byte arrays. The result
282/// is stored in the first array (`a`).
283///
284/// ## Example
285///
286/// ```rust
287/// use libsodium_rs as sodium;
288/// use sodium::utils;
289///
290/// let mut a = [0x01, 0x02, 0x03, 0x04];
291/// let b = [0x00, 0x01, 0x00, 0x01];
292/// utils::add_be(&mut a, &b);
293/// assert_eq!(a, [0x01, 0x03, 0x03, 0x05]);
294/// ```
295///
296/// # Arguments
297/// * `a` - First number as big-endian bytes (will be modified to store the result)
298/// * `b` - Second number as big-endian bytes
299pub fn add_be(a: &mut [u8], b: &[u8]) {
300 unsafe {
301 libsodium_sys::sodium_add(a.as_mut_ptr(), b.as_ptr(), a.len().min(b.len()));
302 }
303}
304
305/// Subtract one number from another, both stored as big-endian bytes
306///
307/// This function subtracts the second number (`b`) from the first number (`a`),
308/// both stored as big-endian byte arrays. The result is stored in the first array (`a`).
309///
310/// ## Example
311///
312/// ```rust
313/// use libsodium_rs as sodium;
314/// use sodium::utils;
315///
316/// let mut a = [0x01, 0x03, 0x03, 0x05];
317/// let b = [0x00, 0x01, 0x00, 0x01];
318/// utils::sub_be(&mut a, &b);
319/// assert_eq!(a, [0x01, 0x02, 0x03, 0x04]);
320/// ```
321///
322/// # Arguments
323/// * `a` - First number as big-endian bytes (will be modified to store the result)
324/// * `b` - Second number as big-endian bytes (will be subtracted from `a`)
325pub fn sub_be(a: &mut [u8], b: &[u8]) {
326 unsafe {
327 libsodium_sys::sodium_sub(a.as_mut_ptr(), b.as_ptr(), a.len().min(b.len()));
328 }
329}
330
331/// Check if a byte array is all zeros
332///
333/// This function checks if a byte array contains only zeros. It is designed to be
334/// constant-time regardless of the input data, which is important for security-sensitive
335/// applications.
336///
337/// ## Example
338///
339/// ```rust
340/// use libsodium_rs as sodium;
341/// use sodium::utils;
342///
343/// let zeros = [0, 0, 0, 0];
344/// let non_zeros = [0, 0, 1, 0];
345///
346/// assert!(utils::is_zero(&zeros));
347/// assert!(!utils::is_zero(&non_zeros));
348/// ```
349///
350/// # Arguments
351/// * `n` - The byte array to check
352///
353/// # Returns
354/// * `bool` - `true` if the array contains only zeros, `false` otherwise
355pub fn is_zero(n: &[u8]) -> bool {
356 unsafe { libsodium_sys::sodium_is_zero(n.as_ptr(), n.len()) == 1 }
357}
358
359/// Compare two byte arrays in lexicographical order
360///
361/// This function compares two byte arrays in lexicographical order. It returns -1 if
362/// the first array is less than the second, 1 if the first array is greater than the
363/// second, and 0 if the arrays are equal. If the shared prefix is equal, the shorter
364/// slice is considered smaller.
365///
366/// ## Security Considerations
367///
368/// - This function is constant-time, which is important for security-sensitive applications
369/// - It should be used when comparing sensitive data that requires a lexicographical
370/// comparison rather than just equality testing
371///
372/// ## Example
373///
374/// ```rust
375/// use libsodium_rs as sodium;
376/// use sodium::utils;
377///
378/// let a = [0x01, 0x02, 0x03, 0x04];
379/// let b = [0x01, 0x02, 0x03, 0x05];
380/// let c = [0x01, 0x02, 0x03, 0x03];
381///
382/// assert_eq!(utils::compare(&a, &b), -1); // a < b
383/// assert_eq!(utils::compare(&b, &a), 1); // b > a
384/// assert_eq!(utils::compare(&a, &a), 0); // a == a
385/// assert_eq!(utils::compare(&a, &c), 1); // a > c
386/// ```
387///
388/// # Arguments
389/// * `a` - First byte array to compare
390/// * `b` - Second byte array to compare
391///
392/// # Returns
393/// * `i32` - -1 if a < b, 1 if a > b, 0 if a == b
394pub fn compare(a: &[u8], b: &[u8]) -> i32 {
395 let min_len = a.len().min(b.len());
396 if min_len > 0 {
397 let cmp = unsafe { libsodium_sys::sodium_compare(a.as_ptr(), b.as_ptr(), min_len) };
398 if cmp != 0 {
399 return cmp;
400 }
401 }
402
403 match a.len().cmp(&b.len()) {
404 std::cmp::Ordering::Less => -1,
405 std::cmp::Ordering::Equal => 0,
406 std::cmp::Ordering::Greater => 1,
407 }
408}
409
410/// Convert binary data to a hexadecimal string
411///
412/// This function converts a byte array to a hexadecimal string representation.
413///
414/// ## Example
415///
416/// ```rust
417/// use libsodium_rs as sodium;
418/// use sodium::utils;
419///
420/// let binary = [0xDE, 0xAD, 0xBE, 0xEF];
421/// let hex = utils::bin2hex(&binary);
422/// assert_eq!(hex, "deadbeef");
423/// ```
424///
425/// # Arguments
426/// * `bin` - The binary data to convert
427///
428/// # Returns
429/// * `String` - The hexadecimal representation of the binary data
430pub fn bin2hex(bin: &[u8]) -> String {
431 let hex_len = bin.len() * 2 + 1;
432 let mut hex = vec![0u8; hex_len];
433
434 unsafe {
435 libsodium_sys::sodium_bin2hex(hex.as_mut_ptr() as *mut _, hex_len, bin.as_ptr(), bin.len());
436 }
437
438 // Remove the null terminator
439 hex.pop();
440
441 // sodium_bin2hex always yields valid UTF-8
442 String::from_utf8(hex).expect("sodium_bin2hex returned invalid UTF-8")
443}
444
445/// Calculate the length of a hexadecimal string needed to encode binary data
446///
447/// This function calculates the length of a hexadecimal string needed to encode
448/// binary data of a given length.
449///
450/// # Arguments
451/// * `bin_len` - The length of the binary data
452///
453/// # Returns
454/// * `usize` - The length of the hexadecimal string, including the null terminator
455pub fn hex_encoded_len(bin_len: usize) -> usize {
456 bin_len * 2 + 1
457}
458
459/// Convert a hexadecimal string to binary data
460///
461/// This function converts a hexadecimal string to binary data.
462///
463/// ## Example
464///
465/// ```rust
466/// use libsodium_rs as sodium;
467/// use sodium::utils;
468///
469/// let hex = "deadbeef";
470/// let binary = utils::hex2bin(hex).unwrap();
471/// assert_eq!(binary, [0xDE, 0xAD, 0xBE, 0xEF]);
472/// ```
473///
474/// # Arguments
475/// * `hex` - The hexadecimal string to convert
476///
477/// # Returns
478/// * `Result<Vec<u8>>` - The binary data or an error if the string is not valid hexadecimal
479pub fn hex2bin(hex: &str) -> Result<Vec<u8>> {
480 let hex_bytes = hex.as_bytes();
481 let bin_len = (hex_bytes.len() + 1) / 2;
482 let mut bin = vec![0u8; bin_len];
483 let mut bin_len_ptr = bin_len;
484
485 let result = unsafe {
486 libsodium_sys::sodium_hex2bin(
487 bin.as_mut_ptr(),
488 bin_len,
489 hex_bytes.as_ptr() as *const _,
490 hex_bytes.len(),
491 std::ptr::null_mut(),
492 &mut bin_len_ptr,
493 std::ptr::null_mut(),
494 )
495 };
496
497 if result != 0 {
498 return Err(crate::SodiumError::HexDecodingFailed);
499 }
500
501 bin.truncate(bin_len_ptr);
502 Ok(bin)
503}
504
505/// Convert a hexadecimal string to binary data, ignoring specified characters
506///
507/// This function converts a hexadecimal string to binary data, ignoring any characters
508/// specified in the `ignore` parameter.
509///
510/// ## Example
511///
512/// ```rust
513/// use libsodium_rs as sodium;
514/// use sodium::utils;
515///
516/// let hex = "de:ad:be:ef";
517/// let binary = utils::hex2bin_ignore(hex, ":").unwrap();
518/// assert_eq!(binary, [0xDE, 0xAD, 0xBE, 0xEF]);
519/// ```
520///
521/// # Arguments
522/// * `hex` - The hexadecimal string to convert
523/// * `ignore` - Characters to ignore in the hexadecimal string
524///
525/// # Returns
526/// * `Result<Vec<u8>>` - The binary data or an error if the string is not valid hexadecimal
527pub fn hex2bin_ignore(hex: &str, ignore: &str) -> Result<Vec<u8>> {
528 let hex_bytes = hex.as_bytes();
529 let ignore_bytes = ignore.as_bytes();
530 let bin_len = (hex_bytes.len() + 1) / 2;
531 let mut bin = vec![0u8; bin_len];
532 let mut bin_len_ptr = bin_len;
533
534 let result = unsafe {
535 libsodium_sys::sodium_hex2bin(
536 bin.as_mut_ptr(),
537 bin_len,
538 hex_bytes.as_ptr() as *const _,
539 hex_bytes.len(),
540 ignore_bytes.as_ptr() as *const _,
541 &mut bin_len_ptr,
542 std::ptr::null_mut(),
543 )
544 };
545
546 if result != 0 {
547 return Err(crate::SodiumError::HexDecodingFailed);
548 }
549
550 bin.truncate(bin_len_ptr);
551 Ok(bin)
552}
553
554/// Calculate the length of a Base64 string needed to encode binary data
555///
556/// This function calculates the length of a Base64 string needed to encode
557/// binary data of a given length, using the specified variant.
558///
559/// # Arguments
560/// * `bin_len` - The length of the binary data
561/// * `variant` - The Base64 variant to use
562///
563/// # Returns
564/// * `usize` - The length of the Base64 string, including the null terminator
565pub fn base64_encoded_len(bin_len: usize, variant: i32) -> usize {
566 unsafe { libsodium_sys::sodium_base64_encoded_len(bin_len, variant) }
567}
568
569/// Convert binary data to a Base64 string
570///
571/// This function converts a byte array to a Base64 string representation,
572/// using the specified variant.
573///
574/// ## Example
575///
576/// ```rust
577/// use libsodium_rs as sodium;
578/// use sodium::utils;
579///
580/// let binary = [0xDE, 0xAD, 0xBE, 0xEF];
581/// let b64 = utils::bin2base64(&binary, utils::BASE64_VARIANT_ORIGINAL);
582/// assert_eq!(b64, "3q2+7w==");
583/// ```
584///
585/// # Arguments
586/// * `bin` - The binary data to convert
587/// * `variant` - The Base64 variant to use
588///
589/// # Returns
590/// * `String` - The Base64 representation of the binary data
591pub fn bin2base64(bin: &[u8], variant: i32) -> String {
592 let b64_len = base64_encoded_len(bin.len(), variant);
593 let mut b64 = vec![0u8; b64_len];
594
595 unsafe {
596 libsodium_sys::sodium_bin2base64(
597 b64.as_mut_ptr() as *mut _,
598 b64_len,
599 bin.as_ptr(),
600 bin.len(),
601 variant,
602 );
603 }
604
605 // Find the null terminator
606 let null_pos = b64.iter().position(|&x| x == 0).unwrap_or(b64.len());
607 b64.truncate(null_pos);
608
609 // sodium_bin2base64 always yields valid UTF-8
610 String::from_utf8(b64).expect("sodium_bin2base64 returned invalid UTF-8")
611}
612
613/// Convert a Base64 string to binary data
614///
615/// This function converts a Base64 string to binary data, using the specified variant.
616///
617/// ## Example
618///
619/// ```rust
620/// use libsodium_rs as sodium;
621/// use sodium::utils;
622///
623/// let b64 = "3q2+7w==";
624/// let binary = utils::base642bin(b64, utils::BASE64_VARIANT_ORIGINAL).unwrap();
625/// assert_eq!(binary, [0xDE, 0xAD, 0xBE, 0xEF]);
626/// ```
627///
628/// # Arguments
629/// * `b64` - The Base64 string to convert
630/// * `variant` - The Base64 variant to use
631///
632/// # Returns
633/// * `Result<Vec<u8>>` - The binary data or an error if the string is not valid Base64
634pub fn base642bin(b64: &str, variant: i32) -> Result<Vec<u8>> {
635 let b64_bytes = b64.as_bytes();
636 let bin_len = (b64_bytes.len() * 3) / 4 + 1;
637 let mut bin = vec![0u8; bin_len];
638 let mut bin_len_ptr = bin_len;
639
640 let result = unsafe {
641 libsodium_sys::sodium_base642bin(
642 bin.as_mut_ptr(),
643 bin_len,
644 b64_bytes.as_ptr() as *const _,
645 b64_bytes.len(),
646 std::ptr::null_mut(),
647 &mut bin_len_ptr,
648 std::ptr::null_mut(),
649 variant,
650 )
651 };
652
653 if result != 0 {
654 return Err(crate::SodiumError::Base64DecodingFailed);
655 }
656
657 bin.truncate(bin_len_ptr);
658 Ok(bin)
659}
660
661/// Secure memory allocation
662///
663/// This function allocates memory with extra protection, including:
664/// - Protection against buffer overflows
665/// - Protection against access after the memory is freed
666/// - Automatic zeroing when freed
667/// - Guarded pages to detect over/underflows
668///
669/// ## Security Considerations
670///
671/// - The allocated memory is automatically zeroed when freed
672/// - The memory is protected from being swapped to disk
673/// - This should be used for storing sensitive data like keys
674///
675/// ## Example
676///
677/// ```no_run
678/// use libsodium_rs as sodium;
679/// use sodium::utils;
680/// use std::slice;
681///
682/// // Allocate 32 bytes of secure memory
683/// let ptr = utils::malloc(32);
684/// assert!(!ptr.is_null());
685///
686/// // Use the memory
687/// unsafe {
688/// let buf = slice::from_raw_parts_mut(ptr as *mut u8, 32);
689/// // Fill with data...
690/// for i in 0..32 {
691/// buf[i] = i as u8;
692/// }
693/// }
694///
695/// // Free the memory (automatically zeroes it)
696/// unsafe {
697/// utils::free(ptr);
698/// }
699/// ```
700///
701/// # Arguments
702/// * `size` - The number of bytes to allocate
703///
704/// # Returns
705/// * `*mut libc::c_void` - A pointer to the allocated memory, or null if allocation failed
706pub fn malloc(size: usize) -> *mut libc::c_void {
707 unsafe { libsodium_sys::sodium_malloc(size) }
708}
709
710/// Allocate an array of elements with secure memory
711///
712/// This function allocates an array of elements with secure memory protection.
713/// It is similar to `malloc`, but allocates an array of elements instead of a
714/// single block of memory.
715///
716/// ## Safety
717/// This function is unsafe because it returns a raw pointer.
718/// The caller is responsible for freeing the memory with `free`.
719///
720/// ## Arguments
721/// * `count` - The number of elements to allocate
722/// * `size` - The size of each element
723///
724/// ## Returns
725/// * `*mut libc::c_void` - A pointer to the allocated memory, or null if allocation failed
726pub fn allocarray(count: usize, size: usize) -> *mut libc::c_void {
727 unsafe { libsodium_sys::sodium_allocarray(count, size) }
728}
729
730/// Free memory allocated by sodium_malloc or sodium_allocarray
731///
732/// This function frees memory that was allocated by `malloc` or `allocarray`.
733/// The memory is automatically zeroed before being freed.
734///
735/// ## Safety
736/// This function is unsafe because it dereferences a raw pointer.
737/// The caller must ensure that the pointer is valid and was allocated by `malloc` or `allocarray`.
738///
739/// ## Arguments
740/// * `ptr` - A pointer to the memory to free
741pub unsafe fn free(ptr: *mut libc::c_void) {
742 unsafe { libsodium_sys::sodium_free(ptr) }
743}
744
745/// Make a region of memory inaccessible
746///
747/// This function makes a region of memory allocated with `malloc` or `allocarray`
748/// inaccessible. It can be made accessible again with `mprotect_readwrite`.
749///
750/// ## Safety
751/// This function is unsafe because it dereferences a raw pointer.
752/// The caller must ensure that the pointer is valid and was allocated by `malloc` or `allocarray`.
753///
754/// ## Arguments
755/// * `ptr` - A pointer to the memory region
756///
757/// ## Returns
758/// * `i32` - 0 on success, -1 on failure
759pub unsafe fn mprotect_noaccess(ptr: *mut libc::c_void) -> i32 {
760 unsafe { libsodium_sys::sodium_mprotect_noaccess(ptr) }
761}
762
763/// Make a region of memory read-only
764///
765/// This function makes a region of memory allocated with `malloc` or `allocarray`
766/// read-only. It can be made writable again with `mprotect_readwrite`.
767///
768/// ## Safety
769/// This function is unsafe because it dereferences a raw pointer.
770/// The caller must ensure that the pointer is valid and was allocated by `malloc` or `allocarray`.
771///
772/// ## Arguments
773/// * `ptr` - A pointer to the memory region
774///
775/// ## Returns
776/// * `i32` - 0 on success, -1 on failure
777pub unsafe fn mprotect_readonly(ptr: *mut libc::c_void) -> i32 {
778 unsafe { libsodium_sys::sodium_mprotect_readonly(ptr) }
779}
780
781/// Make a region of memory readable and writable
782///
783/// This function makes a region of memory allocated with `malloc` or `allocarray`
784/// readable and writable.
785///
786/// ## Safety
787/// This function is unsafe because it dereferences a raw pointer.
788/// The caller must ensure that the pointer is valid and was allocated by `malloc` or `allocarray`.
789///
790/// ## Arguments
791/// * `ptr` - A pointer to the memory region
792///
793/// ## Returns
794/// * `i32` - 0 on success, -1 on failure
795pub unsafe fn mprotect_readwrite(ptr: *mut libc::c_void) -> i32 {
796 unsafe { libsodium_sys::sodium_mprotect_readwrite(ptr) }
797}
798
799// Export the vec_utils module
800pub mod vec_utils;
801
802// Re-export SecureVec and secure_vec from vec_utils
803pub use vec_utils::{secure_vec, SecureVec};