Skip to content

Commit

Permalink
Feat/bls qa (#256)
Browse files Browse the repository at this point in the history
* Update comments, remove logs and update test

* Update zemu test

* Use target to define constants

* Do not render non-ascii characters

* Update zxlib

* New abstractions for msg rendering

* Check for reply to be Ok from the canister

* reduce binary size

* Add new resource for UI consent message response

* Move iterator to its own module
Use iterator and add another Msg struct to cach number of items and optimize review flow

Use new UI resource
Update zxlib

Export heardbeat and util function to debug numbers

Use consentInfo as the ui handlers

Fix warnings

Use panic abort and reduce binary size

Update test and pad with spaces

Adjust test as we do not longer support screen width smaller that lines

Serialize test

Update snapshots

* Update bindings

* Omit tests as we need more suitable testing data

* Make clippy happy

* Fix snapshots and update version

* Remove ram setting from makefile as it causes errors in nanos

* some cleanups
  • Loading branch information
neithanmo authored Dec 24, 2024
1 parent 6ff61fe commit c065697
Show file tree
Hide file tree
Showing 355 changed files with 477 additions and 475 deletions.
1 change: 0 additions & 1 deletion app/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ endif

APP_LOAD_PARAMS = --curve secp256k1 $(COMMON_LOAD_PARAMS) --path $(APPPATH)

APP_STACK_MIN_SIZE := 2050
include $(CURDIR)/../deps/ledger-zxlib/makefiles/Makefile.devices
RUST_TARGET := thumbv6m-none-eabi

Expand Down
2 changes: 1 addition & 1 deletion app/Makefile.version
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ APPVERSION_M=3
# This is the minor version of this release
APPVERSION_N=2
# This is the patch version of this release
APPVERSION_P=1
APPVERSION_P=2
5 changes: 4 additions & 1 deletion app/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@ serde = { version = "1.0.215", features = ["derive"] }
no-std-compat = { version = "0.4.1", features = ["std"] }

[profile.release]
lto = false
codegen-units = 1
debug = false
opt-level = "z"
lto = "thin"
overflow-checks = false
strip = "symbols"
panic = "abort"

[profile.dev]
panic = "abort"
Expand Down
10 changes: 10 additions & 0 deletions app/rust/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fn main() {
let target = std::env::var("RUST_TARGET_NAME").unwrap_or_default();
match target.as_str() {
"TARGET_STAX" => println!("cargo:rustc-cfg=device_stax"),
"TARGET_FLEX" => println!("cargo:rustc-cfg=device_flex"),
"TARGET_NANOS2" => println!("cargo:rustc-cfg=device_nanos2"),
"TARGET_NANOX" => println!("cargo:rustc-cfg=device_nanox"),
_ => println!("cargo:rustc-cfg=device_nanos"), // default
}
}
17 changes: 12 additions & 5 deletions app/rust/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
********************************************************************************/

pub const MAX_PAGES: usize = 10;
// Configuration constants based on target device
// means max number of lines per page
pub const MAX_LINES: usize = 3;
// means max characteres per line
// this is a limit of the device
// intended to control the already formatted
// message response comming
// from canisters
pub const MAX_CHARS_PER_LINE: usize = 35;

pub const BLS_PUBLIC_KEY_SIZE: usize = 96;
pub const BLS_SIGNATURE_SIZE: usize = 48;
// means max characteres per line
pub const MAX_LINES: usize = 3;
// means mx number of lines per page
pub const MAX_PAGES: usize = 10;
pub const MAX_CHARS_PER_LINE: usize = 25;
pub const REPLY_PATH: &str = "reply";
pub const CANISTER_RANGES_PATH: &str = "canister_ranges";

Expand Down
3 changes: 3 additions & 0 deletions app/rust/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ pub enum ParserError {
FieldNotFound,
LEB128Overflow,
InvalidTime,
TooManyLines,
TooManyPages,
LineTooLong,
}

// minicibor error provides a reach
Expand Down
14 changes: 11 additions & 3 deletions app/rust/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,15 @@ mod ffi_verify_cert {
const CONSENT: &str = "d9d9f7a167636f6e74656e74a76361726758d84449444c086d7b6e766c02aeaeb1cc0501d880c6d007716c02cbaeb581017ab183e7f1077a6b028beabfc2067f8ef1c1ee0d036e046c02efcee7800402c4fbf2db05056c03d6fca70200e1edeb4a7184f7fee80a060107684449444c066e7d6d7b6e016e786c02b3b0dac30368ad86ca8305026c08c6fcb60200ba89e5c20402a2de94eb060282f3f3910c03d8a38ca80d7d919c9cbf0d00dea7f7da0d03cb96dcb40e04010501904e0000008094ebdc030000010a00000000000000070101000d69637263325f617070726f76650002656e0101230003006b63616e69737465725f69644a000000000000000201016e696e67726573735f6578706972791b18072a6f7894d0006b6d6574686f645f6e616d6578246963726332315f63616e69737465725f63616c6c5f636f6e73656e745f6d657373616765656e6f6e636550369f1914fd64438f5e6329fcb66b1d4d6c726571756573745f747970656463616c6c6673656e6465724104";
const ROOT_KEY: &str =
"b354faa40626ebc91ed7e55b2307feff70d119ef37f89915bd4561a1ed8c5c26c8c2cb8c4711eec681bf213a75cb988008fb1f4d7aa278cd4fad6f295c83bab04b8cabcb32640cf926083daf865551f9f3b76fd800dac027a583858b9d1d3f64";
const CERT2: &str = "d9d9f7a264747265658301830182045820f7ce39e353276ef7eac40214d6294a53d45c840988b3ad8d0655230bac1893d483018204582045c8d9bed81048bbe60926bf8585350ba6bbe6523d6f5f994fff922edbdef96e83024e726571756573745f737461747573830183018301820458202d1afceef6681d8b8a48dbc7dcde236ad09ff53487b5f65c86f402c4019c81e08301830183018301830182045820bda400ec9debeeaf0e8e4dc6308cf1d0ccc2f6861984ffe8cb5c0f7ddd006bdd830183018301830182045820c3a04b54583072b58beab029efcbd9d9f2191c061fda4c79dfcd554f57534b598302582034a44c265c7ff6c8e4ed5c3d442f12b8b52580f800ffb892a89ad56b3167a62683018302457265706c7982035903304449444c0c6b02bc8a0101c5fed201096c02efcee7800402e29fdcc806046c02aeaeb1cc0503d880c6d007716e766b02d9e5b0980405fcdfd79a0f716c01c4d6b4ea0b066d076c01ffbb87a807086d716b04d1c4987c0aa3f2efe6020b9a8597e6030be3c581900f0b6c02fc91f4f80571c498b1b50d7d6c01fc91f4f805710100000002656e0007031e2320417574686f72697a6520616e6f74686572206164647265737320746f2077697468647261772066726f6d20796f7572206163636f756e74202a2a5468651f666f6c6c6f77696e67206164647265737320697320616c6c6f77656420746f031d77697468647261772066726f6d20796f7572206163636f756e743a2a2a2272646d78362d6a616161612d61616161612d61616164712d636169202a2a596f75720d7375626163636f756e743a2a2a032330303030303030303030303030303030303030303030303030303030303030303030301d3030303030303030303030303030303030303030303030303030303030232a2a526571756573746564207769746864726177616c20616c6c6f77616e63653a2a2a032031302049435020e29aa02054686520616c6c6f77616e63652077696c6c2062652273657420746f2031302049435020696e646570656e64656e746c79206f6620616e791e70726576696f757320616c6c6f77616e63652e20556e74696c207468697303217472616e73616374696f6e20686173206265656e206578656375746564207468651e7370656e6465722063616e207374696c6c206578657263697365207468652370726576696f757320616c6c6f77616e63652028696620616e792920746f2069742773032166756c6c20616d6f756e742e202a2a45787069726174696f6e20646174653a2a2a204e6f2065787069726174696f6e2e202a2a417070726f76616c206665653a2a2a23302e3030303120494350202a2a5472616e73616374696f6e206665657320746f206265031a7061696420627920796f7572207375626163636f756e743a2a2a2330303030303030303030303030303030303030303030303030303030303030303030301d30303030303030303030303030303030303030303030303030303030308302467374617475738203477265706c696564820458205c1a351ac2b7a24b96afcaf767521613b4fd3e577aee74769266cf9f36637d4e8204582068041707ea8d374da007bb1a7a0e0bed07ab24f04b026f7986fc2a85a8fe126282045820b1dcc25b9e681479a3a0c8e48f7ec659cba3a8d2432d9da3539993e3d07ca1be820458200a9b91be81767b301772430b1e4e3347c17b107de0fd585c88108d613550f1758204582035d8238a10e9bb5c4181e35da06ebebba1aea87bb3d144b2dda13c9fcba042f4820458205f41f1b3eda637ed957dbb173be06810a3518eeca57efee3538fbded7a146ef182045820642f92e0236f3dfa2becc643a3aa9703aa4c998360b67d57b03961fdf6c704fe82045820a2092115cfa051b579b9e20a04a9d711fe65e960e47a883a7971ae348af2100282045820175aaba4eea75ae431612394d2dc78fe5058c846466011f311b90b3b5df77000830182045820bc995b4159ff52ed2d587118a4260a039b6141b7af942d7f482c34b37d62e53c83024474696d65820349c18af7abc1d9fe8618697369676e61747572655830a272688e94dffcee62a658d41a6c19cf5f531bc5d1f238ffea80706fc8ffa878cb760a68bf32fa596c651652d2e00a2a";
const CALL2: &str = "d9d9f7a167636f6e74656e74a76361726758684449444c066e7d6d7b6e016e786c02b3b0dac30368ad86ca8305026c08c6fcb60200ba89e5c20402a2de94eb060282f3f3910c03d8a38ca80d7d919c9cbf0d00dea7f7da0d03cb96dcb40e04010501904e0000008094ebdc030000010a00000000000000070101006b63616e69737465725f69644a000000000000000201016e696e67726573735f6578706972791b180dfaf93de928006b6d6574686f645f6e616d656d69637263325f617070726f7665656e6f6e63655007726649d5ee68e7bd09c853a5dac0fc6c726571756573745f747970656463616c6c6673656e646572581d052c5f6f270fc4a3a882a8075732cba90ad4bd25d30bd2cf7b0bfe7c02";
const CONSENT2: &str = "d9d9f7a167636f6e74656e74a76361726758d84449444c086d7b6e766c02aeaeb1cc0501d880c6d007716c02cbaeb581017ab183e7f1077a6b028beabfc2067f8ef1c1ee0d036e046c02efcee7800402c4fbf2db05056c03d6fca70200e1edeb4a7184f7fee80a060107684449444c066e7d6d7b6e016e786c02b3b0dac30368ad86ca8305026c08c6fcb60200ba89e5c20402a2de94eb060282f3f3910c03d8a38ca80d7d919c9cbf0d00dea7f7da0d03cb96dcb40e04010501904e0000008094ebdc030000010a00000000000000070101000d69637263325f617070726f76650002656e0101230003006b63616e69737465725f69644a000000000000000201016e696e67726573735f6578706972791b180dfaf93de928006b6d6574686f645f6e616d6578246963726332315f63616e69737465725f63616c6c5f636f6e73656e745f6d657373616765656e6f6e636550b70f2ce7f8f414041610c3d3d4eab6d06c726571756573745f747970656463616c6c6673656e6465724104";
const ROOT_KEY2: &str = "814c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d9685f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484b01291091c5f87b98883463f98091a0baaae";

fn bls_flow(cert: &str, call: &str, consent: &str) -> u32 {
fn bls_flow(cert: &str, call: &str, consent: &str, root_key: &str) -> u32 {
let cert_data = hex::decode(cert).unwrap();
let call_data = hex::decode(call).unwrap();
let root_key = hex::decode(ROOT_KEY).unwrap();
let root_key = hex::decode(root_key).unwrap();
let consent_data = hex::decode(consent).unwrap();

unsafe {
Expand Down Expand Up @@ -74,10 +78,14 @@ mod ffi_verify_cert {

#[test]
fn test_bls_flow() {
let res = bls_flow(CERT, CALL, CONSENT);
let t1 = (CERT, CALL, CONSENT, ROOT_KEY);
let t2 = (CERT2, CALL2, CONSENT2, ROOT_KEY2);
let res = bls_flow(t1.0, t1.1, t1.2, t1.3);
assert_eq!(res, ParserError::Ok as u32);
unsafe {
rs_clear_resources();
}
let res = bls_flow(t2.0, t2.1, t2.2, t2.3);
assert_eq!(res, ParserError::Ok as u32);
}
}
6 changes: 5 additions & 1 deletion app/rust/src/ffi/resources.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bolos::{lazy_static, pic::PIC};

use crate::Certificate;
use crate::{consent_message::msg_info::ConsentInfo, Certificate};

use super::{call_request::CanisterCallT, consent_request::ConsentRequestT};

Expand All @@ -17,10 +17,14 @@ pub static mut MEMORY_CALL_REQUEST: [u8; core::mem::size_of::<CanisterCallT>()];
#[lazy_static]
pub static mut CERTIFICATE: Option<Certificate<'static>> = None;

#[lazy_static]
pub static mut UI: Option<ConsentInfo<'static>> = None;

#[no_mangle]
pub unsafe extern "C" fn rs_clear_resources() {
// zeroize data
_ = MEMORY_CONSENT_REQUEST.write(0, &[0; core::mem::size_of::<ConsentRequestT>()]);
_ = MEMORY_CALL_REQUEST.write(0, &[0; core::mem::size_of::<CanisterCallT>()]);
CERTIFICATE.take();
UI.take();
}
14 changes: 7 additions & 7 deletions app/rust/src/ffi/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@

use crate::{error::ParserError, DisplayableItem};

use super::resources::CERTIFICATE;
use super::resources::UI;

#[no_mangle]
pub unsafe extern "C" fn rs_getNumItems(num_items: *mut u8) -> u32 {
crate::zlog("rs_getNumItems\x00");
if num_items.is_null() || !CERTIFICATE.is_some() {
if num_items.is_null() || !UI.is_some() {
return ParserError::ContextMismatch as u32;
}

// Safe to unwrap due to previous check
let cert = CERTIFICATE.as_ref().unwrap();
let ui = UI.as_ref().unwrap();

let Ok(num) = cert.num_items() else {
let Ok(num) = ui.num_items() else {
crate::zlog("no_DATA\x00");
return ParserError::NoData as _;
};
Expand Down Expand Up @@ -56,14 +56,14 @@ pub unsafe extern "C" fn rs_getItem(
let key = core::slice::from_raw_parts_mut(out_key as *mut u8, key_len as usize);
let value = core::slice::from_raw_parts_mut(out_value as *mut u8, out_len as usize);

if !CERTIFICATE.is_some() {
if !UI.is_some() {
return ParserError::ContextMismatch as _;
}

// Safe to unwrap due to previous check
let cert = CERTIFICATE.as_ref().unwrap();
let ui = UI.as_ref().unwrap();

match cert.render_item(display_idx, key, value, page_idx) {
match ui.render_item(display_idx, key, value, page_idx) {
Ok(page) => {
*page_count = page;
ParserError::Ok as _
Expand Down
21 changes: 11 additions & 10 deletions app/rust/src/ffi/verify_certificate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use crate::{
check_canary,
consent_message::msg_response::ConsentMessageResponse,
constants::{BLS_PUBLIC_KEY_SIZE, DEFAULT_SENDER},
error::ParserError,
Certificate, FromBytes, HashTree, LookupResult, Principal,
Expand All @@ -30,7 +31,7 @@ use super::{
c_api::device_principal,
call_request::CanisterCallT,
consent_request::ConsentRequestT,
resources::{CERTIFICATE, MEMORY_CALL_REQUEST, MEMORY_CONSENT_REQUEST},
resources::{CERTIFICATE, MEMORY_CALL_REQUEST, MEMORY_CONSENT_REQUEST, UI},
};

// This is use to check important fields in consent_msg_request and canister_call_request
Expand Down Expand Up @@ -67,12 +68,10 @@ pub unsafe extern "C" fn rs_verify_certificate(
}

// Check values are set
crate::zlog("call_request****\x00");
let Ok(call_request) = CanisterCallT::from_bytes(&**MEMORY_CALL_REQUEST) else {
return ParserError::NoData as u32;
};

crate::zlog("consent_request****\x00");
let Ok(consent_request) = ConsentRequestT::from_bytes(&**MEMORY_CONSENT_REQUEST) else {
return ParserError::NoData as u32;
};
Expand All @@ -81,7 +80,6 @@ pub unsafe extern "C" fn rs_verify_certificate(
// for canister_call_t and consent_request_t
// which ensures canister_id, method and args are the same in both
if call_request != consent_request {
crate::zlog("call != consent mistmatch\x00");
return ParserError::InvalidCertificate as u32;
}

Expand All @@ -94,7 +92,6 @@ pub unsafe extern "C" fn rs_verify_certificate(

let mut cert = MaybeUninit::uninit();
let Ok(_) = Certificate::from_bytes_into(data, &mut cert) else {
crate::zlog("Fail parsing certificate***\x00");
return ParserError::InvalidCertificate as u32;
};

Expand All @@ -112,21 +109,18 @@ pub unsafe extern "C" fn rs_verify_certificate(
let Ok(LookupResult::Found(_)) =
HashTree::lookup_path(&consent_request.request_id[..].into(), cert.tree())
else {
crate::zlog("request_id mismatch****\x00");
return ParserError::InvalidCertificate as u32;
};

//
// Verify ingress_expiry aginst certificate timestamp
if !cert.verify_time(call_request.ingress_expiry) {
crate::zlog("ingress_expiry mismatch****\x00");
return ParserError::InvalidCertificate as u32;
}

let call_sender = &call_request.sender[..call_request.sender_len as usize];
let consent_sender = &consent_request.sender[..consent_request.sender_len as usize];

if !validate_sender(call_sender, consent_sender) {
crate::zlog("sender_id mismatch****\x00");
return ParserError::InvalidCertificate as u32;
}

Expand All @@ -136,11 +130,18 @@ pub unsafe extern "C" fn rs_verify_certificate(
if !ranges.is_canister_in_range(
&call_request.canister_id[..call_request.canister_id_len as usize],
) {
crate::zlog("canister_id mismatch****\x00");
return ParserError::InvalidCertificate as u32;
}
}

// Check for the response type embedded in the certificate
// an error response means we can not go further
let Ok(ConsentMessageResponse::Ok(ui)) = cert.msg_response() else {
return ParserError::InvalidCertificate as u32;
};

UI.replace(ui);

// Indicates certificate was valid
CERTIFICATE.replace(cert);

Expand Down
37 changes: 30 additions & 7 deletions app/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,46 @@ fn panic(_info: &PanicInfo) -> ! {
}

pub fn zlog(_msg: &str) {
#[cfg(not(test))]
#[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing")))]
unsafe {
zemu_log_stack(_msg.as_bytes().as_ptr());
}
#[cfg(test)]
std::println!("{}", _msg);
}

#[cfg(not(test))]
pub fn check_canary() {
unsafe { check_app_canary() }
#[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing")))]
unsafe {
_check_canary()
}
}

#[cfg(test)]
pub fn check_canary() {}

extern "C" {
fn zemu_log_stack(s: *const u8);
fn check_app_canary();
fn _check_canary();
fn log_number(e: *const u8, number: u32);
}

#[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing")))]
extern "C" {
fn io_heartbeat();
}

// Lets the device breath between computations
pub(crate) fn heartbeat() {
#[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing")))]
unsafe {
io_heartbeat()
}
}

// Lets the device breath between computations
pub(crate) fn log_num(s: &str, number: u32) {
#[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing")))]
unsafe {
log_number(s.as_bytes().as_ptr(), number);
}
#[cfg(test)]
std::println!("{s}: {number}");
}
Loading

0 comments on commit c065697

Please sign in to comment.