Skip to content

Commit e7bd47d

Browse files
authored
Allow building without std on nightly (#10)
* allow building without stdlib by no_std feature * document serde * Fix tests * cargo fmt * Reword around `std` vs `no_std`
1 parent 4218d49 commit e7bd47d

File tree

10 files changed

+99
-29
lines changed

10 files changed

+99
-29
lines changed

.github/workflows/ci.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ jobs:
3939
with:
4040
command: test
4141

42+
- uses: actions-rs/cargo@v1
43+
with:
44+
command: test
45+
args: --no-default-features --features serde --manifest-path oqs/Cargo.toml
46+
47+
- uses: actions-rs/cargo@v1
48+
with:
49+
command: test
50+
args: --no-default-features --features no_std,serde --manifest-path oqs/Cargo.toml
51+
4252
- uses: actions-rs/cargo@v1
4353
with:
4454
command: fmt

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@ oqs = "0.2"
3232

3333
``oqs-sys`` can be specified equivalently.
3434

35+
Serde support
36+
-------------
37+
38+
You can enable ``serde`` serialization support by enabling the ``serde`` feature on the ``oqs`` rcate.
39+
40+
`no_std` support
41+
----------------
42+
43+
The ``oqs-sys`` crate does not use `std` at all.
44+
Note that the default features do enable building liboqs with ``openssl``, so use ``default-features = false``.
45+
46+
For ``no_std`` suport in the ``oqs`` crate, enable the ``no_std`` feature.
47+
Make sure to also disable the ``oqs-sys/openssl`` feature by specifying ``default-features = false``.
48+
49+
3550
Running
3651
-------
3752

oqs-sys/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ exclude = ["liboqs/tests/**", "liboqs/docs/**", "liboqs/scripts/**", "build/**/*
1515
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1616

1717
[dependencies]
18+
libc = "0.2"
1819

1920
[build-dependencies]
2021
cmake = "0.1"

oqs-sys/build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ fn generate_bindings(outdir: &PathBuf, headerfile: &str, filter: &str) {
2424
.whitelist_type(filter)
2525
.whitelist_function(filter)
2626
.whitelist_var(filter)
27+
// Use core and libc
28+
.use_core()
29+
.ctypes_prefix("::libc")
2730
// Finish the builder and generate the bindings.
2831
.generate()
2932
// Unwrap the Result and panic on failure.

oqs-sys/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//! Bindings to liboqs
2+
#![no_std]
3+
14
#[allow(clippy::all)]
25
#[allow(non_upper_case_globals)]
36
#[allow(non_camel_case_types)]

oqs/Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@ repository = "https://github.com/open-quantum-safe/liboqs-rust"
99
license = "MIT OR Apache-2.0"
1010

1111
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
12-
1312
[dependencies]
14-
serde = { version = "1.0", optional = true, features = ["derive"] }
13+
libc = "0.2"
14+
cstr_core = { version = "0.2", default-features = false, features = ["alloc"], optional = true }
15+
serde = { version = "1.0", optional = true, default-features = false, features = ["derive", "alloc"] }
1516

1617
[dependencies.oqs-sys]
1718
path = "../oqs-sys"
1819
version = "0.2.0"
1920
default-features = false
2021

2122
[features]
23+
no_std = ["cstr_core"]
2224
default = ["oqs-sys/openssl"]

oqs/src/kem.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
//! KEM API
22
//!
33
//! See [`Kem`] for the main functionality
4-
use crate::ffi::kem as ffi;
5-
use crate::*;
6-
use std::os::raw;
7-
use std::ptr::NonNull;
4+
use alloc::borrow;
5+
use alloc::vec::Vec;
6+
7+
use core::ptr::NonNull;
8+
9+
#[cfg(feature = "no_std")]
10+
use cstr_core::CStr;
11+
#[cfg(not(feature = "no_std"))]
12+
use std::ffi::CStr;
813

914
#[cfg(feature = "serde")]
1015
use serde::{Deserialize, Serialize};
1116

17+
use crate::ffi::kem as ffi;
1218
use crate::newtype_buffer;
19+
use crate::*;
1320

1421
newtype_buffer!(PublicKey, PublicKeyRef);
1522
newtype_buffer!(SecretKey, SecretKeyRef);
@@ -33,7 +40,7 @@ macro_rules! implement_kems {
3340
)*
3441
}
3542

36-
fn algorithm_to_id(algorithm: Algorithm) -> *const raw::c_char {
43+
fn algorithm_to_id(algorithm: Algorithm) -> *const libc::c_char {
3744
let id: &[u8] = match algorithm {
3845
$(
3946
Algorithm::$kem => &ffi::$oqs_id[..],
@@ -130,7 +137,7 @@ implement_kems! {
130137
SikeP751Compressed: OQS_KEM_alg_sike_p751_compressed,
131138
}
132139

133-
impl std::default::Default for Algorithm {
140+
impl core::default::Default for Algorithm {
134141
fn default() -> Self {
135142
Algorithm::Default
136143
}
@@ -146,7 +153,7 @@ impl Algorithm {
146153
/// Provides a pointer to the id of the algorithm
147154
///
148155
/// For use with the FFI api methods
149-
pub fn to_id(self) -> *const raw::c_char {
156+
pub fn to_id(self) -> *const libc::c_char {
150157
algorithm_to_id(self)
151158
}
152159
}
@@ -172,16 +179,16 @@ impl Kem {
172179
}
173180

174181
/// Get the name of the algorithm
175-
pub fn name(&self) -> std::borrow::Cow<str> {
182+
pub fn name(&self) -> borrow::Cow<str> {
176183
let kem = unsafe { self.kem.as_ref() };
177-
let cstr = unsafe { std::ffi::CStr::from_ptr(kem.method_name) };
184+
let cstr = unsafe { CStr::from_ptr(kem.method_name) };
178185
cstr.to_string_lossy()
179186
}
180187

181188
/// Get the version of the implementation
182-
pub fn version(&self) -> std::borrow::Cow<str> {
189+
pub fn version(&self) -> borrow::Cow<str> {
183190
let kem = unsafe { self.kem.as_ref() };
184-
let cstr = unsafe { std::ffi::CStr::from_ptr(kem.method_name) };
191+
let cstr = unsafe { CStr::from_ptr(kem.method_name) };
185192
cstr.to_string_lossy()
186193
}
187194

oqs/src/lib.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![warn(missing_docs)]
2+
#![cfg_attr(feature = "no_std", no_std)]
23
//! Friendly bindings to liboqs
34
//!
45
//! See the [`kem::Kem`] and [`sig::Sig`] structs for how to use this crate.
@@ -37,7 +38,10 @@
3738
//! Ok(())
3839
//! }
3940
//! ```
41+
// needs to be imported to be made available
42+
extern crate alloc;
4043

44+
#[cfg(not(feature = "no_std"))]
4145
use std::sync::Once;
4246

4347
use ffi::common::OQS_STATUS;
@@ -51,14 +55,26 @@ mod macros;
5155
///
5256
/// Make sure to call this before you use any of the functions.
5357
///
54-
/// This method is thread-safe and can be called more than once.
58+
/// When the `no_std` feature is not enabled, this method is thread-safe
59+
/// and can be called more than once.
60+
#[cfg(not(feature = "no_std"))]
5561
pub fn init() {
5662
static INIT: Once = Once::new();
5763
INIT.call_once(|| {
5864
unsafe { ffi::common::OQS_init() };
5965
});
6066
}
6167

68+
/// Initialize liboqs
69+
///
70+
/// Needs to be called before you use any of the functions.
71+
///
72+
/// This no_std variant is not thread-safe.
73+
#[cfg(feature = "no_std")]
74+
pub fn init() {
75+
unsafe { ffi::common::OQS_init() };
76+
}
77+
6278
#[derive(Debug)]
6379
#[non_exhaustive]
6480
/// Possible errors
@@ -70,13 +86,14 @@ pub enum Error {
7086
/// Error occurred in OpenSSL functions external to liboqs
7187
ErrorExternalOpenSSL,
7288
}
89+
#[cfg(not(feature = "no_std"))]
7390
impl std::error::Error for Error {}
7491

7592
/// Result type for operations that may fail
76-
pub type Result<T> = std::result::Result<T, Error>;
93+
pub type Result<T> = core::result::Result<T, Error>;
7794

78-
impl std::fmt::Display for Error {
79-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95+
impl core::fmt::Display for Error {
96+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8097
match self {
8198
Error::AlgorithmDisabled => write!(f, "Algorithm has been disabled"),
8299
_ => write!(f, "OQS Error!"),

oqs/src/macros.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ macro_rules! newtype_buffer {
4848
}
4949
}
5050

51-
impl<'a> std::ops::Deref for $name_ref<'a> {
51+
impl<'a> core::ops::Deref for $name_ref<'a> {
5252
type Target = [u8];
5353
fn deref(&self) -> &Self::Target {
5454
&self.bytes
@@ -72,6 +72,12 @@ macro_rules! newtype_buffer {
7272

7373
#[cfg(test)]
7474
mod test {
75+
use alloc::vec;
76+
use alloc::vec::Vec;
77+
78+
#[cfg(feature = "serde")]
79+
use serde::{Deserialize, Serialize};
80+
7581
newtype_buffer!(TestBuf, TestBufRef);
7682

7783
#[test]

oqs/src/sig.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
//! Signature API
22
//!
33
//! See [`Sig`] for the main functionality
4+
use alloc::borrow;
5+
use alloc::vec::Vec;
46

5-
use crate::ffi::sig as ffi;
6-
use crate::*;
7-
use std::os::raw;
8-
use std::ptr::NonNull;
7+
use core::ptr::NonNull;
8+
9+
#[cfg(feature = "no_std")]
10+
use cstr_core::CStr;
11+
#[cfg(not(feature = "no_std"))]
12+
use std::ffi::CStr;
913

14+
use crate::ffi::sig as ffi;
1015
use crate::newtype_buffer;
16+
use crate::*;
1117

1218
#[cfg(feature = "serde")]
1319
use serde::{Deserialize, Serialize};
@@ -35,7 +41,7 @@ macro_rules! implement_sigs {
3541
)*
3642
}
3743

38-
fn algorithm_to_id(algorithm: Algorithm) -> *const raw::c_char {
44+
fn algorithm_to_id(algorithm: Algorithm) -> *const libc::c_char {
3945
let id: &[u8] = match algorithm {
4046
$(
4147
Algorithm::$sig => &ffi::$oqs_id[..],
@@ -136,7 +142,7 @@ implement_sigs! {
136142
SphincsShake256256sSimple: OQS_SIG_alg_sphincs_shake256_256s_simple,
137143
}
138144

139-
impl std::default::Default for Algorithm {
145+
impl core::default::Default for Algorithm {
140146
fn default() -> Self {
141147
Algorithm::Default
142148
}
@@ -152,7 +158,7 @@ impl Algorithm {
152158
/// Provides a pointer to the id of the algorithm
153159
///
154160
/// For use with the FFI api methods
155-
pub fn to_id(self) -> *const raw::c_char {
161+
pub fn to_id(self) -> *const libc::c_char {
156162
algorithm_to_id(self)
157163
}
158164
}
@@ -178,16 +184,16 @@ impl Sig {
178184
}
179185

180186
/// Get the name of this signature algorithm
181-
pub fn name(&self) -> std::borrow::Cow<str> {
187+
pub fn name(&self) -> borrow::Cow<str> {
182188
let sig = unsafe { self.sig.as_ref() };
183-
let cstr = unsafe { std::ffi::CStr::from_ptr(sig.method_name) };
189+
let cstr = unsafe { CStr::from_ptr(sig.method_name) };
184190
cstr.to_string_lossy()
185191
}
186192

187193
/// Version of this implementation
188-
pub fn version(&self) -> std::borrow::Cow<str> {
194+
pub fn version(&self) -> borrow::Cow<str> {
189195
let sig = unsafe { self.sig.as_ref() };
190-
let cstr = unsafe { std::ffi::CStr::from_ptr(sig.method_name) };
196+
let cstr = unsafe { CStr::from_ptr(sig.method_name) };
191197
cstr.to_string_lossy()
192198
}
193199

0 commit comments

Comments
 (0)