Repository: randombit/botan-rs (language: rust)

Issue:
Support no_std
We can get the C types via `libc`, which supports `no_std`.


Discussion / hints:
This requires removing use of `Vec` which would be a major change in API but probably worthwhile overall.
Good first step would be to just support `no_std` within `botan-sys`, which just requires using the libc types.
Think the trick is to implement `no_std` compatible APIs that write to/read from slices, and then in situations when `std` is available implement the current API on top of the `no_std` implementations.
FFI CString requires `libstd` so I think we are SOL here
Some hope of progress in https://github.com/rust-lang/rust/issues/46736

Alternatively can DIY it ala https://gitlab.com/worr/rcstring/blob/master/src/lib.rs

Fix patch:
diff --git a/botan/Cargo.toml b/botan/Cargo.toml
index 6eadba5..f89d9bc 100644
--- a/botan/Cargo.toml
+++ b/botan/Cargo.toml
@@ -22,3 +22,8 @@ status = "actively-developed"
 botan-sys = { version = "0.5.0", path = "../botan-sys" }
 # we don't need std support
 libc = { version = "0.2", default-features = false }
+cstr_core = { version = "0.1", optional = true }
+
+[features]
+default = []
+no-std = ["cstr_core/alloc"]
diff --git a/botan/src/lib.rs b/botan/src/lib.rs
index de44340..ad7f0f8 100644
--- a/botan/src/lib.rs
+++ b/botan/src/lib.rs
@@ -5,6 +5,16 @@
 
 //! A wrapper for the Botan cryptography library
 
+#![cfg_attr(feature = "no-std", feature(alloc))]
+#![cfg_attr(feature = "no-std", no_std)]
+
+#[cfg(feature = "no-std")]
+#[macro_use]
+extern crate alloc;
+
+#[cfg(feature = "no-std")]
+extern crate cstr_core;
+
 extern crate botan_sys;
 extern crate libc;
 
diff --git a/botan/src/mp.rs b/botan/src/mp.rs
index c6ce160..67fe95f 100644
--- a/botan/src/mp.rs
+++ b/botan/src/mp.rs
@@ -3,11 +3,11 @@ use crate::utils::*;
 
 use crate::rng::RandomNumberGenerator;
 
-use std::cmp::{Eq, Ord, Ordering};
-use std::fmt;
-use std::str::FromStr;
+use core::cmp::{Eq, Ord, Ordering};
+use core::fmt;
+use core::str::FromStr;
 
-use std::ops::{Add, AddAssign,
+use core::ops::{Add, AddAssign,
                Sub, SubAssign,
                Mul, MulAssign,
                Div, DivAssign,
@@ -137,7 +137,7 @@ impl MPI {
     /// Return value of self as decimal string
     pub fn to_string(&self) -> Result<String> {
         let bit_count = self.bit_count()? as f64;
-        let log_base = (10f64).log2();
+        let log_base = 3.3219; // log2(10)
         let bn_digits = 1 + (bit_count / log_base) as usize;
 
         call_botan_ffi_returning_string(bn_digits, &|out_buf, out_len| {
@@ -369,7 +369,7 @@ impl MPI {
     /// # Examples
     ///
     /// ```
-    /// use std::str::FromStr;
+    /// use core::str::FromStr;
     /// let n = botan::MPI::from_str("1111111111111111111").unwrap();
     /// let rng = botan::RandomNumberGenerator::new_system().unwrap();
     /// assert!(n.is_prime(&rng, 128).unwrap());
@@ -387,7 +387,7 @@ impl MPI {
     /// # Examples
     ///
     /// ```
-    /// use std::str::FromStr;
+    /// use core::str::FromStr;
     /// let x = botan::MPI::from_str("1111111111111111").unwrap();
     /// let y = botan::MPI::from_str("111111111111").unwrap();
     /// assert_eq!(botan::MPI::gcd(&x, &y).unwrap(), botan::MPI::from_str("1111").unwrap());
diff --git a/botan/src/otp.rs b/botan/src/otp.rs
index 7fff215..f1e2ced 100644
--- a/botan/src/otp.rs
+++ b/botan/src/otp.rs
@@ -57,7 +57,6 @@ impl HOTP {
     /// Check an HOTP code
     pub fn check(&self, code: u32, counter: u64) -> Result<bool> {
         let cmp_code = self.generate(counter)?;
-        println!("{} {}", code, cmp_code);
         Ok(cmp_code == code)
     }
 
diff --git a/botan/src/utils.rs b/botan/src/utils.rs
index a666611..eaada80 100644
--- a/botan/src/utils.rs
+++ b/botan/src/utils.rs
@@ -1,12 +1,20 @@
 use botan_sys::*;
 
-pub(crate) use libc::{c_char, c_int, c_void};
+#[cfg(feature = "no-std")]
+pub(crate) use alloc::prelude::*;
+
+#[cfg(feature = "no-std")]
+pub(crate) use cstr_core::{CStr, CString};
+
+#[cfg(not(feature = "no-std"))]
 pub(crate) use std::ffi::{CStr, CString};
-pub(crate) use std::ptr;
-pub(crate) use std::mem;
+
+pub(crate) use libc::{c_char, c_int, c_void};
+pub(crate) use core::ptr;
+pub(crate) use core::mem;
 
 /// The result of calling an operation on the library
-pub type Result<T> = ::std::result::Result<T, Error>;
+pub type Result<T> = ::core::result::Result<T, Error>;
 
 pub(crate) fn make_cstr(input: &str) -> Result<CString> {
     let cstr = CString::new(input).map_err(|_| Error::ConversionError)?;


Test patch: