botan/
memutils.rs

1use crate::utils::*;
2use botan_sys::*;
3
4/// Const time comparison
5///
6/// Compare two arrays without leaking side channel information
7#[must_use]
8pub fn const_time_compare<T: Copy>(a: &[T], b: &[T]) -> bool {
9    if a.len() != b.len() {
10        return false;
11    }
12
13    let bytes = mem::size_of_val(a);
14    let rc = unsafe {
15        botan_constant_time_compare(a.as_ptr() as *const u8, b.as_ptr() as *const u8, bytes)
16    };
17
18    rc == 0
19}
20
21/// Securely zeroize memory
22///
23/// Write zeros to the array (eg to clear out a key) in a way that is
24/// unlikely to be removed by the compiler.
25pub fn scrub_mem<T: Copy>(a: &mut [T]) {
26    let bytes = mem::size_of_val(a);
27    unsafe { botan_scrub_mem(a.as_mut_ptr() as *mut c_void, bytes) };
28}
29
30/// Hex encode some data
31pub fn hex_encode(x: &[u8]) -> Result<String> {
32    let flags = 0u32;
33
34    let mut output = vec![0u8; x.len() * 2];
35    botan_call!(
36        botan_hex_encode,
37        x.as_ptr(),
38        x.len(),
39        output.as_mut_ptr() as *mut c_char,
40        flags
41    )?;
42
43    String::from_utf8(output).map_err(Error::conversion_error)
44}
45
46/// Hex decode some data
47pub fn hex_decode(x: &str) -> Result<Vec<u8>> {
48    let mut output = vec![0u8; x.len() / 2];
49    let mut output_len = output.len();
50
51    let input = make_cstr(x)?;
52
53    botan_call!(
54        botan_hex_decode,
55        input.as_ptr(),
56        x.len(),
57        output.as_mut_ptr(),
58        &mut output_len
59    )?;
60
61    output.resize(output_len, 0);
62
63    Ok(output)
64}
65
66/// Base64 encode some data
67///
68/// # Examples
69///
70/// ```
71/// assert_eq!(botan::base64_encode(&[97,98,99,100,101,102]).unwrap(), "YWJjZGVm");
72/// assert_eq!(botan::base64_encode(&[0x5A, 0x16, 0xAD, 0x4E, 0x17, 0x87, 0x79, 0xC9]).unwrap(), "WhatTheHeck=");
73/// ```
74pub fn base64_encode(x: &[u8]) -> Result<String> {
75    let b64_len = 1 + ((x.len() + 2) / 3) * 4;
76
77    call_botan_ffi_returning_string(b64_len, &|out_buf, out_len| unsafe {
78        botan_base64_encode(x.as_ptr(), x.len(), out_buf as *mut c_char, out_len)
79    })
80}
81
82/// Base64 decode some data
83///
84/// # Examples
85///
86/// ```
87/// assert!(botan::base64_decode("ThisIsInvalid!").is_err());
88/// assert_eq!(botan::base64_decode("YWJjZGVm").unwrap(), b"abcdef");
89/// ```
90pub fn base64_decode(x: &str) -> Result<Vec<u8>> {
91    // Hard to provide a decent lower bound as it is possible x includes
92    // lots of spaces or trailing = padding chars
93    let bin_len = x.len();
94
95    let input = make_cstr(x)?;
96
97    call_botan_ffi_returning_vec_u8(bin_len, &|out_buf, out_len| unsafe {
98        botan_base64_decode(input.as_ptr(), x.len(), out_buf, out_len)
99    })
100}