Skip to content

Commit 88282f9

Browse files
committed
feat: no_std
1 parent 20f8b22 commit 88282f9

File tree

8 files changed

+102
-53
lines changed

8 files changed

+102
-53
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "scal3"
33
description = "Verify that systems operate under your sole control (prototype, patent pending)"
44
license = "CC-BY-NC-4.0"
5-
version = "0.3.5"
5+
version = "0.3.7"
66
edition = "2021"
77
repository = "https://github.com/cleverbase/scal3"
88
authors = ["Sander Dijkhuis <sander.dijkhuis@cleverbase.com>"]
@@ -28,6 +28,7 @@ minicbor-derive = "0.16.2"
2828
serde = { version = "1.0.219", features = ["derive"] }
2929
serde_bytes = "0.11.17"
3030
once_cell = "1.21.3"
31+
spin = { version = "0.9.8", default-features = false, features = ["mutex", "once", "spin_mutex"] }
3132

3233
[dev-dependencies]
3334
hmac = "0.12.1"

src/api/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::domain::Authentication;
22
use crate::handle::insert_authentication;
33
use crate::{domain, program};
44
use serde::{Deserialize, Serialize};
5+
use alloc::string::String;
56

67
/// Enrolled verification data for the [subscriber].
78
///

src/dispatch.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::api::{
55
use crate::handle::get_authentication;
66
use crate::{Error, ErrorResponse, Response};
77
use serde::Deserialize;
8+
use alloc::vec::Vec;
89

910
#[derive(Deserialize)]
1011
#[serde(tag = "type", rename_all = "camelCase")]

src/domain.rs

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ use p256::{ecdsa, FieldBytes, ProjectivePoint, PublicKey};
2323
use rand_chacha::ChaCha20Rng;
2424
use sha2::{Digest, Sha256};
2525
use signature::{Signer, Verifier as SignatureVerifier};
26-
use std::collections::BTreeMap;
27-
use std::io::Write;
26+
use alloc::collections::BTreeMap;
27+
use alloc::vec::Vec;
2828

2929
pub(crate) struct Verifier {
3030
blinded_subscriber_share: p256::Scalar,
@@ -46,18 +46,41 @@ pub(crate) struct Pass {
4646
impl Pass {
4747
pub(crate) fn to_bytes(&self) -> [u8; 308] {
4848
let mut encoded = [0u8; 308];
49-
let mut buf = &mut encoded[..];
50-
buf.write_all(&challenge_to_bytes(self.subscriber_commitments))
51-
.unwrap(); // 66
52-
buf.write_all(&self.authenticator_proof.sig_device.to_bytes())
53-
.unwrap(); // 64
54-
buf.write_all(self.binding.pk.to_encoded_point(true).as_bytes())
55-
.unwrap(); // 33
56-
buf.write_all(&self.binding.signature.to_bytes()).unwrap(); // 64
57-
buf.write_all(&pk_sender_to_bytes(&self.pk_kem_sender))
58-
.unwrap(); // 33
59-
buf.write_all(&self.sealed_signature_share).unwrap(); // 32
60-
buf.write_all(&self.tag.to_bytes()).unwrap(); // 16
49+
let mut offset = 0;
50+
51+
// 66 bytes
52+
let challenge_bytes = challenge_to_bytes(self.subscriber_commitments);
53+
encoded[offset..offset + 66].copy_from_slice(&challenge_bytes);
54+
offset += 66;
55+
56+
// 64 bytes
57+
let sig_device_bytes = self.authenticator_proof.sig_device.to_bytes();
58+
encoded[offset..offset + 64].copy_from_slice(&sig_device_bytes);
59+
offset += 64;
60+
61+
// 33 bytes
62+
let pk_bytes = self.binding.pk.to_encoded_point(true);
63+
encoded[offset..offset + 33].copy_from_slice(pk_bytes.as_bytes());
64+
offset += 33;
65+
66+
// 64 bytes
67+
let signature_bytes = self.binding.signature.to_bytes();
68+
encoded[offset..offset + 64].copy_from_slice(&signature_bytes);
69+
offset += 64;
70+
71+
// 33 bytes
72+
let pk_sender_bytes = pk_sender_to_bytes(&self.pk_kem_sender);
73+
encoded[offset..offset + 33].copy_from_slice(&pk_sender_bytes);
74+
offset += 33;
75+
76+
// 32 bytes
77+
encoded[offset..offset + 32].copy_from_slice(&self.sealed_signature_share);
78+
offset += 32;
79+
80+
// 16 bytes
81+
let tag_bytes = self.tag.to_bytes();
82+
encoded[offset..offset + 16].copy_from_slice(&tag_bytes);
83+
6184
encoded
6285
}
6386

@@ -151,11 +174,22 @@ impl ClientExtensionTranscript {
151174
impl ClientExtensionTranscript {
152175
pub(crate) fn to_bytes(&self) -> [u8; 129] {
153176
let mut encoded = [0u8; 129];
154-
let mut buf = &mut encoded[..];
155-
buf.write_all(&self.pk_binding.to_encoded_point(true).as_bytes())
156-
.unwrap();
157-
buf.write_all(&self.sig_binding.to_bytes()).unwrap();
158-
buf.write_all(&self.sig_joint_second.to_bytes()).unwrap();
177+
let mut offset = 0;
178+
179+
// 33 bytes
180+
let pk_binding_bytes = self.pk_binding.to_encoded_point(true);
181+
encoded[offset..offset + 33].copy_from_slice(pk_binding_bytes.as_bytes());
182+
offset += 33;
183+
184+
// 64 bytes
185+
let sig_binding_bytes = self.sig_binding.to_bytes();
186+
encoded[offset..offset + 64].copy_from_slice(&sig_binding_bytes);
187+
offset += 64;
188+
189+
// 32 bytes
190+
let sig_joint_second_bytes = self.sig_joint_second.to_bytes();
191+
encoded[offset..offset + 32].copy_from_slice(&sig_joint_second_bytes);
192+
159193
encoded
160194
}
161195
}
@@ -187,7 +221,7 @@ pub(crate) struct Provider {
187221
#[derive(Debug, PartialEq)]
188222
pub(crate) struct VerificationError;
189223

190-
pub(crate) type Result = std::result::Result<(), VerificationError>;
224+
pub(crate) type Result = core::result::Result<(), VerificationError>;
191225

192226
fn aad(masked_subscriber_share: &p256::Scalar, pk_joint: &frost::VerifyingKey) -> Vec<u8> {
193227
[
@@ -665,7 +699,7 @@ mod test {
665699
let mut rng_hpke = rand_chacha::ChaCha20Rng::from_seed(seed);
666700
let (sk_r, pk_r) = DhP256HkdfSha256::gen_keypair(&mut rng_hpke);
667701
let verifier = Verifier::new(&pk_r, &mask, &mut rng_hpke);
668-
println!("size of share: {:?}", verifier.sealed_provider_share.len());
702+
// Removed println! for no_std compatibility
669703
let shared_secret = dh(&sk_r, &verifier.pk_kem_subscriber);
670704
let s = verifier.verify(shared_secret, &pk_r);
671705
assert!(s.is_some());

src/ffi.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
use crate::dispatch::dispatch;
2+
use core::slice;
3+
use core::mem;
4+
use alloc::vec::Vec;
25

36
/// Dispatches a CBOR-encoded request and outputs a CBOR-encoded response, which must be freed using [free].
47
#[export_name = "scal3_process"]
@@ -8,11 +11,11 @@ pub unsafe extern "C" fn process(
811
output_ptr: *mut *mut u8,
912
output_len: *mut usize,
1013
) {
11-
let input = std::slice::from_raw_parts(input_ptr, input_len);
14+
let input = slice::from_raw_parts(input_ptr, input_len);
1215
let vec = dispatch(input);
1316
let len = vec.len();
1417
let ptr = vec.as_ptr();
15-
std::mem::forget(vec);
18+
mem::forget(vec);
1619
*output_ptr = ptr as *mut u8;
1720
*output_len = len;
1821
}

src/handle.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
1-
use std::collections::HashMap;
2-
use std::sync::Mutex;
1+
use alloc::collections::BTreeMap;
2+
use alloc::boxed::Box;
3+
use spin::Mutex;
34
use crate::domain::Authentication;
4-
use once_cell::sync::Lazy;
5+
use spin::Once;
56

6-
static CONTEXTS: Lazy<Mutex<HashMap<u64, Box<Authentication>>>> = Lazy::new(Default::default);
7-
static NEXT_ID: Lazy<Mutex<u64>> = Lazy::new(|| Mutex::new(1));
7+
static CONTEXTS: Once<Mutex<BTreeMap<u64, Box<Authentication>>>> = Once::new();
8+
static NEXT_ID: Once<Mutex<u64>> = Once::new();
9+
10+
fn get_contexts() -> &'static Mutex<BTreeMap<u64, Box<Authentication>>> {
11+
CONTEXTS.call_once(|| Mutex::new(BTreeMap::new()))
12+
}
13+
14+
fn get_next_id() -> &'static Mutex<u64> {
15+
NEXT_ID.call_once(|| Mutex::new(1))
16+
}
817

918
pub fn insert_authentication(authentication: Authentication) -> u64 {
10-
let mut authentications = CONTEXTS.lock().unwrap();
11-
let mut next = NEXT_ID.lock().unwrap();
19+
let mut authentications = get_contexts().lock();
20+
let mut next = get_next_id().lock();
1221
let id = *next;
1322
*next += 1;
1423
authentications.insert(id, Box::new(authentication));
1524
id
1625
}
1726

1827
pub fn get_authentication(id: u64) -> Option<Box<Authentication>> {
19-
CONTEXTS.lock().unwrap().remove(&id)
28+
get_contexts().lock().remove(&id)
2029
}

src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
#![no_std]
12
#![doc = include_str!("README.md")]
23

4+
#[cfg(test)]
5+
extern crate std;
6+
7+
extern crate alloc;
8+
39
pub(crate) mod api;
410
mod dispatch;
511
mod domain;
@@ -13,7 +19,7 @@ use api::*;
1319
pub use dispatch::dispatch;
1420
pub use ffi::*;
1521
use getrandom::register_custom_getrandom;
16-
use std::num::NonZeroU32;
22+
use core::num::NonZeroU32;
1723

1824
const CUSTOM_ERROR_CODE: u32 = getrandom::Error::CUSTOM_START + 0;
1925
fn stub_get_random(_buf: &mut [u8]) -> Result<(), getrandom::Error> {

src/program/provider.rs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::domain;
33
use crate::domain::{pk_recipient_from_bytes, shared_secret_from_bytes, Provider, Result, VerificationError};
44
use hpke::Serializable;
55
use p256::elliptic_curve::sec1::ToEncodedPoint;
6-
use std::io::Write;
6+
77

88
pub(crate) fn accept(
99
provider: &Key,
@@ -25,23 +25,17 @@ pub(crate) fn challenge(randomness: &Randomness) -> Challenge {
2525
};
2626
let (_, commitments) = provider.challenge();
2727
let mut challenge = [0u8; 66];
28-
let mut buffer = &mut challenge[..];
29-
buffer
30-
.write_all(
31-
p256::PublicKey::from_sec1_bytes(&commitments.hiding().serialize().unwrap())
32-
.unwrap()
33-
.to_encoded_point(true)
34-
.as_bytes(),
35-
)
36-
.unwrap();
37-
buffer
38-
.write_all(
39-
p256::PublicKey::from_sec1_bytes(&commitments.binding().serialize().unwrap())
40-
.unwrap()
41-
.to_encoded_point(true)
42-
.as_bytes(),
43-
)
44-
.unwrap();
28+
// 33 bytes for hiding commitment
29+
let hiding_point = p256::PublicKey::from_sec1_bytes(&commitments.hiding().serialize().unwrap())
30+
.unwrap()
31+
.to_encoded_point(true);
32+
challenge[0..33].copy_from_slice(hiding_point.as_bytes());
33+
34+
// 33 bytes for binding commitment
35+
let binding_point = p256::PublicKey::from_sec1_bytes(&commitments.binding().serialize().unwrap())
36+
.unwrap()
37+
.to_encoded_point(true);
38+
challenge[33..66].copy_from_slice(binding_point.as_bytes());
4539
challenge
4640
}
4741

@@ -81,7 +75,7 @@ mod tests {
8175
#[test]
8276
fn test_challenge() {
8377
let randomness = [1u8; 32];
84-
let challenge = challenge(&randomness);
85-
println!("{:x?}", challenge);
78+
let _challenge = challenge(&randomness);
79+
// Removed println! for no_std compatibility
8680
}
8781
}

0 commit comments

Comments
 (0)