|
|
|
@ -22,7 +22,7 @@ use base64::{Engine, engine::general_purpose::STANDARD};
|
|
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
#[allow(non_camel_case_types)]
|
|
|
|
|
pub enum Base64ReturnCode {
|
|
|
|
|
pub enum SCBase64ReturnCode {
|
|
|
|
|
SC_BASE64_OK = 0,
|
|
|
|
|
SC_BASE64_INVALID_ARG,
|
|
|
|
|
SC_BASE64_OVERFLOW,
|
|
|
|
@ -30,7 +30,7 @@ pub enum Base64ReturnCode {
|
|
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
|
|
|
pub enum Base64Mode {
|
|
|
|
|
pub enum SCBase64Mode {
|
|
|
|
|
/* If the following strings were to be passed to the decoder with RFC2045 mode,
|
|
|
|
|
* the results would be as follows. See the unittest B64TestVectorsRFC2045 in
|
|
|
|
|
* src/util-base64.c
|
|
|
|
@ -46,8 +46,8 @@ pub enum Base64Mode {
|
|
|
|
|
* BASE64("foobar") = "Zm$9vYm.Fy" # According to RFC 2045, All line breaks or *other
|
|
|
|
|
* characters* not found in base64 alphabet must be ignored by decoding software
|
|
|
|
|
* */
|
|
|
|
|
Base64ModeRFC2045 = 0, /* SPs are allowed during transfer but must be skipped by Decoder */
|
|
|
|
|
Base64ModeStrict,
|
|
|
|
|
SCBase64ModeRFC2045 = 0, /* SPs are allowed during transfer but must be skipped by Decoder */
|
|
|
|
|
SCBase64ModeStrict,
|
|
|
|
|
/* If the following strings were to be passed to the decoder with RFC4648 mode,
|
|
|
|
|
* the results would be as follows. See the unittest B64TestVectorsRFC4648 in
|
|
|
|
|
* src/util-base64.c
|
|
|
|
@ -63,11 +63,11 @@ pub enum Base64Mode {
|
|
|
|
|
* BASE64("f") = "Zm$9vYm.Fy" <-- Notice how the processing stops once an invalid char is
|
|
|
|
|
* encountered
|
|
|
|
|
* */
|
|
|
|
|
Base64ModeRFC4648, /* reject the encoded data if it contains characters outside the base alphabet */
|
|
|
|
|
SCBase64ModeRFC4648, /* reject the encoded data if it contains characters outside the base alphabet */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
pub unsafe extern "C" fn Base64DecodeBufferSize(input_len: u32) -> u32 {
|
|
|
|
|
pub unsafe extern "C" fn SCBase64DecodeBufferSize(input_len: u32) -> u32 {
|
|
|
|
|
return get_decoded_buffer_size(input_len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -76,10 +76,10 @@ pub unsafe extern "C" fn Base64DecodeBufferSize(input_len: u32) -> u32 {
|
|
|
|
|
/// This method exposes the Rust base64 decoder to C and should not be called from
|
|
|
|
|
/// Rust code.
|
|
|
|
|
///
|
|
|
|
|
/// It allows decoding in the modes described by ``Base64Mode`` enum.
|
|
|
|
|
/// It allows decoding in the modes described by ``SCBase64Mode`` enum.
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
pub unsafe extern "C" fn Base64Decode(
|
|
|
|
|
input: *const u8, len: usize, mode: Base64Mode, output: *mut u8) -> u32 {
|
|
|
|
|
pub unsafe extern "C" fn SCBase64Decode(
|
|
|
|
|
input: *const u8, len: usize, mode: SCBase64Mode, output: *mut u8) -> u32 {
|
|
|
|
|
if input.is_null() || len == 0 {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@ -89,19 +89,19 @@ pub unsafe extern "C" fn Base64Decode(
|
|
|
|
|
let mut num_decoded: u32 = 0;
|
|
|
|
|
let mut decoder = Decoder::new();
|
|
|
|
|
match mode {
|
|
|
|
|
Base64Mode::Base64ModeRFC2045 => {
|
|
|
|
|
SCBase64Mode::SCBase64ModeRFC2045 => {
|
|
|
|
|
if decode_rfc2045(&mut decoder, in_vec, out_vec, &mut num_decoded).is_err() {
|
|
|
|
|
debug_validate_bug_on!(num_decoded >= len as u32);
|
|
|
|
|
return num_decoded;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Base64Mode::Base64ModeRFC4648 => {
|
|
|
|
|
SCBase64Mode::SCBase64ModeRFC4648 => {
|
|
|
|
|
if decode_rfc4648(&mut decoder, in_vec, out_vec, &mut num_decoded).is_err() {
|
|
|
|
|
debug_validate_bug_on!(num_decoded >= len as u32);
|
|
|
|
|
return num_decoded;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Base64Mode::Base64ModeStrict => {
|
|
|
|
|
SCBase64Mode::SCBase64ModeStrict => {
|
|
|
|
|
if let Ok(decoded_len) = STANDARD.decode_slice(in_vec, out_vec) {
|
|
|
|
|
num_decoded = decoded_len as u32;
|
|
|
|
|
}
|
|
|
|
@ -118,31 +118,31 @@ pub unsafe extern "C" fn Base64Decode(
|
|
|
|
|
/// Rust code.
|
|
|
|
|
///
|
|
|
|
|
/// The output parameter must be an allocated buffer of at least the size returned
|
|
|
|
|
/// from Base64EncodeBufferSize for the input_len, and this length must be provided
|
|
|
|
|
/// from SCBase64EncodeBufferSize for the input_len, and this length must be provided
|
|
|
|
|
/// in the output_len variable.
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
pub unsafe extern "C" fn Base64Encode(
|
|
|
|
|
pub unsafe extern "C" fn SCBase64Encode(
|
|
|
|
|
input: *const u8, input_len: c_ulong, output: *mut c_uchar, output_len: *mut c_ulong,
|
|
|
|
|
) -> Base64ReturnCode {
|
|
|
|
|
) -> SCBase64ReturnCode {
|
|
|
|
|
if input.is_null() || output.is_null() || output_len.is_null() {
|
|
|
|
|
return Base64ReturnCode::SC_BASE64_INVALID_ARG;
|
|
|
|
|
return SCBase64ReturnCode::SC_BASE64_INVALID_ARG;
|
|
|
|
|
}
|
|
|
|
|
let input = std::slice::from_raw_parts(input, input_len as usize);
|
|
|
|
|
let encoded = STANDARD.encode(input);
|
|
|
|
|
if encoded.len() + 1 > *output_len as usize {
|
|
|
|
|
return Base64ReturnCode::SC_BASE64_OVERFLOW;
|
|
|
|
|
return SCBase64ReturnCode::SC_BASE64_OVERFLOW;
|
|
|
|
|
}
|
|
|
|
|
let output = std::slice::from_raw_parts_mut(&mut *output, *output_len as usize);
|
|
|
|
|
output[0..encoded.len()].copy_from_slice(encoded.as_bytes());
|
|
|
|
|
output[encoded.len()] = 0;
|
|
|
|
|
*output_len = encoded.len() as c_ulong;
|
|
|
|
|
Base64ReturnCode::SC_BASE64_OK
|
|
|
|
|
SCBase64ReturnCode::SC_BASE64_OK
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Ratio of output bytes to input bytes for Base64 Encoding is 4:3, hence the
|
|
|
|
|
/// required output bytes are 4 * ceil(input_len / 3) and an additional byte for
|
|
|
|
|
/// storing the NULL pointer.
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
pub extern "C" fn Base64EncodeBufferSize(len: c_ulong) -> c_ulong {
|
|
|
|
|
pub extern "C" fn SCBase64EncodeBufferSize(len: c_ulong) -> c_ulong {
|
|
|
|
|
(4 * ((len) + 2) / 3) + 1
|
|
|
|
|
}
|
|
|
|
|