Skip to content

Commit

Permalink
Merge pull request #40 from Zondax/masp-signing
Browse files Browse the repository at this point in the history
Masp signing
  • Loading branch information
chcmedeiros authored May 24, 2024
2 parents 71e2c21 + e6a3ec3 commit a27fed2
Show file tree
Hide file tree
Showing 270 changed files with 64,865 additions and 8,245 deletions.
37 changes: 25 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#*******************************************************************************
#* (c) 2018 -2022 Zondax AG
#* (c) 2018 -2024 Zondax AG
#*
#* Licensed under the Apache License, Version 2.0 (the "License");
#* you may not use this file except in compliance with the License.
Expand All @@ -14,12 +14,22 @@
#* limitations under the License.
#********************************************************************************
cmake_minimum_required(VERSION 3.0)
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.25.5.tar.gz"
SHA1 "a20151e4c0740ee7d0f9994476856d813cdead29"
LOCAL
)

project(ledger-namada VERSION 0.0.0)
enable_testing()

cmake_policy(SET CMP0025 NEW)
set(CMAKE_CXX_STANDARD 11)

set(HUNTER_STATUS_DEBUG ON)
set(HUNTER_TLS_VERIFY OFF)

option(ENABLE_FUZZING "Build with fuzzing instrumentation and build fuzz targets" OFF)
option(ENABLE_COVERAGE "Build with source code coverage instrumentation" OFF)
option(ENABLE_SANITIZERS "Build with ASAN and UBSAN" OFF)
Expand All @@ -31,6 +41,13 @@ string(APPEND CMAKE_LINKER_FLAGS " -fno-omit-frame-pointer -g")
add_definitions(-DAPP_STANDARD)
add_definitions(-DSUBSTRATE_PARSER_FULL)

hunter_add_package(fmt)
find_package(fmt CONFIG REQUIRED)
hunter_add_package(jsoncpp)
find_package(jsoncpp CONFIG REQUIRED)
hunter_add_package(GTest)
find_package(GTest CONFIG REQUIRED)

if(ENABLE_FUZZING)
add_definitions(-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1)
SET(ENABLE_SANITIZERS ON CACHE BOOL "Sanitizer automatically enabled" FORCE)
Expand Down Expand Up @@ -72,9 +89,6 @@ if(ENABLE_SANITIZERS)
string(APPEND CMAKE_LINKER_FLAGS " -fsanitize=address,undefined -fsanitize-recover=address,undefined")
endif()

include(cmake/conan/CMakeLists.txt)
add_subdirectory(cmake/gtest)

set (RETRIEVE_MAJOR_CMD
"cat ${CMAKE_CURRENT_SOURCE_DIR}/app/Makefile.version | grep APPVERSION_M | cut -b 14- | tr -d '\n'"
)
Expand Down Expand Up @@ -122,6 +136,9 @@ file(GLOB_RECURSE LIB_SRC
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl_common.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl_txn.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl_masp.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/bech32_encoding.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_address.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/crypto_helper.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/leb128.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/txn_validator.c
Expand Down Expand Up @@ -202,25 +219,21 @@ file(GLOB_RECURSE TESTS_SRC

add_executable(unittests ${TESTS_SRC})
target_include_directories(unittests PRIVATE
${gtest_SOURCE_DIR}/include
${gmock_SOURCE_DIR}/include
${CONAN_INCLUDE_DIRS_FMT}
${CONAN_INCLUDE_DIRS_JSONCPP}
${CMAKE_CURRENT_SOURCE_DIR}/app/src
${CMAKE_CURRENT_SOURCE_DIR}/app/src/lib
###
${CMAKE_CURRENT_SOURCE_DIR}/deps/blake2/ref
)

target_link_libraries(unittests PRIVATE
gtest_main
GTest::gtest_main
app_lib
rslib
CONAN_PKG::fmt
CONAN_PKG::jsoncpp)
fmt::fmt
JsonCpp::JsonCpp)

add_compile_definitions(TESTVECTORS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/tests/")
add_test(unittests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittests)
add_test(NAME unittests COMMAND unittests)
set_tests_properties(unittests PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)

##############################################################
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2018-2022 Zondax AG
Copyright 2018-2024 Zondax AG

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#*******************************************************************************
#* (c) 2018 - 2023 Zondax AG
#* (c) 2018 - 2024 Zondax AG
#*
#* Licensed under the Apache License, Version 2.0 (the "License");
#* you may not use this file except in compliance with the License.
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ This project contains the Namada app for Ledger Nano S Nano S+ and X.
- C++ unit tests
- Zemu tests

## Disclaimer
MASP Key generation and signing not supported in NanoS

## ATTENTION

Please:
Expand Down
2 changes: 1 addition & 1 deletion app/LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2018-2022 Zondax AG
Copyright 2018-2024 Zondax AG

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion app/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#*******************************************************************************
# Ledger App
# (c) 2018 - 2022 Zondax AG
# (c) 2018 - 2024 Zondax AG
# (c) 2017 Ledger
#
# Licensed under the Apache License, Version 2.0 (the "License");
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=0
# This is the `spec_version` field of `Runtime`
APPVERSION_N=0
# This is the patch version of this release
APPVERSION_P=21
APPVERSION_P=22
4 changes: 4 additions & 0 deletions app/rust/include/rslib.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ parser_error_t scalar_multiplication(const uint8_t input[32], constant_key_t key
parser_error_t get_default_diversifier_list(const uint8_t dk[32], uint8_t start_index[11], uint8_t d_l[44]);
parser_error_t get_default_diversifier(const uint8_t dk[32], uint8_t start_index[11], uint8_t d[11]);
parser_error_t get_pkd(const uint8_t ivk_ptr[32], const uint8_t hash[32], uint8_t pk_d[32]);
parser_error_t get_pkd(const uint8_t ivk_ptr[32], const uint8_t hash[32], uint8_t pk_d[32]);
bool is_valid_diversifier(const uint8_t hash[32]);
parser_error_t randomized_secret_from_seed(const uint8_t ask[32], const uint8_t alpha[32], uint8_t output[32]);
parser_error_t compute_sbar(const uint8_t s[32], uint8_t r[32], uint8_t rsk[32], uint8_t sbar[32]);
parser_error_t add_points(const uint8_t hash[32], const uint8_t value[32], const uint8_t scalar[32], uint8_t cv[32]);
17 changes: 17 additions & 0 deletions app/rust/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,23 @@ pub const PROOF_GENERATION_KEY_GENERATOR: AffineNielsPoint = AffinePoint::from_r
)
.to_niels();


pub const VALUE_COMMITMENT_RANDOMNESS_GENERATOR: AffineNielsPoint = AffinePoint::from_raw_unchecked(
Fq::from_raw([
0xdd93d364cb8cec7e,
0x91cc3e3835675450,
0xcfa86026b8d99be9,
0x1c6da0ce9a5e5fdb,
]),
Fq::from_raw([
0x28e5fce99ce692d0,
0xf94c2daa360302fe,
0xbc900cd4b8ae1150,
0x555f11f9b720d50b,
]),
)
.to_niels();

pub const DIV_SIZE: usize = 11;
pub const DIV_DEFAULT_LIST_LEN: usize = 4;
pub const KEY_DIVERSIFICATION_PERSONALIZATION: &[u8; 8] = b"MASP__gd";
Expand Down
55 changes: 55 additions & 0 deletions app/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub enum ParserError {
pub enum ConstantKey {
SpendingKeyGenerator,
ProofGenerationKeyGenerator,
ValueCommitmentRandomnessGenerator,
}

#[no_mangle]
Expand All @@ -62,6 +63,7 @@ pub extern "C" fn scalar_multiplication(
let key_point = match key {
ConstantKey::SpendingKeyGenerator => constants::SPENDING_KEY_GENERATOR,
ConstantKey::ProofGenerationKeyGenerator => constants::PROOF_GENERATION_KEY_GENERATOR,
ConstantKey::ValueCommitmentRandomnessGenerator => constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR,
};

let extended_point = key_point.multiply_bits(input);
Expand Down Expand Up @@ -146,6 +148,59 @@ pub extern "C" fn get_pkd(
ParserError::ParserOk
}

#[no_mangle]
pub extern "C" fn randomized_secret_from_seed(
ask: &[u8; 32],
alpha: &[u8; 32],
output: &mut [u8; 32],
) -> ParserError{

let mut skfr = Fr::from_bytes(ask).unwrap();
let alphafr = Fr::from_bytes(alpha).unwrap();
skfr += alphafr;
output.copy_from_slice(&skfr.to_bytes());

ParserError::ParserOk
}

#[no_mangle]
pub extern "C" fn compute_sbar(
s: &[u8; 32],
r: &[u8; 32],
rsk: &[u8; 32],
sbar: &mut [u8; 32],
) -> ParserError{
let s_point = Fr::from_bytes(s).unwrap();
let r_point = Fr::from_bytes(r).unwrap();
let rsk_point = Fr::from_bytes(rsk).unwrap();

let sbar_tmp = r_point + s_point * rsk_point;
sbar.copy_from_slice(&sbar_tmp.to_bytes());
ParserError::ParserOk
}

#[no_mangle]
pub extern "C" fn add_points(
hash: &[u8; 32],
value: &[u8; 32],
scalar: &[u8; 32],
cv: &mut [u8; 32]) -> ParserError{

let hash_point = AffinePoint::from_bytes(*hash).unwrap();
let hash_point_ex = ExtendedPoint::from(hash_point);
let cofactor = hash_point_ex.mul_by_cofactor();

let val = Fr::from_bytes(value).unwrap();

let scale = AffinePoint::from_bytes(*scalar).unwrap();
let scale_extended = ExtendedPoint::from(scale);

let s = cofactor*val + scale_extended;
let vcm = AffinePoint::from(s).to_bytes();
cv.copy_from_slice(&vcm);
ParserError::ParserOk
}

#[cfg(not(test))]
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
Expand Down
2 changes: 1 addition & 1 deletion app/src/addr.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* (c) 2018 - 2022 Zondax AG
* (c) 2018 - 2024 Zondax AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion app/src/addr.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* (c) 2018 - 2022 Zondax AG
* (c) 2018 - 2024 Zondax AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
80 changes: 77 additions & 3 deletions app/src/apdu_handler.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* (c) 2018 - 2022 Zondax AG
* (c) 2018 - 2024 Zondax AG
* (c) 2016 Ledger
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -29,7 +29,6 @@
#include "addr.h"
#include "crypto.h"
#include "coin.h"
#include "transparent.h"
#include "zxmacros.h"
#include "view_internal.h"
#include "review_keys.h"
Expand Down Expand Up @@ -124,6 +123,29 @@ __Z_INLINE void handleSignTransaction(volatile uint32_t *flags, volatile uint32_
*flags |= IO_ASYNCH_REPLY;
}

__Z_INLINE void handleSignMasp(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
ZEMU_LOGF(50, "handleSignMasp\n")
if (!process_chunk(tx, rx)) {
THROW(APDU_CODE_OK);
}
CHECK_APP_CANARY()

const char *error_msg = tx_parse();
CHECK_APP_CANARY()

if (error_msg != NULL) {
const int error_msg_length = strnlen(error_msg, sizeof(G_io_apdu_buffer));
memcpy(G_io_apdu_buffer, error_msg, error_msg_length);
*tx += (error_msg_length);
THROW(APDU_CODE_DATA_INVALID);
}

CHECK_APP_CANARY()
view_review_init(tx_getItem, tx_getNumItems, app_sign_masp);
view_review_show(REVIEW_TXN);
*flags |= IO_ASYNCH_REPLY;
}

// For wrapper transactions, address is derived from Ed25519 pubkey
__Z_INLINE void handleGetAddr(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
zemu_log("handleGetAddr\n");
Expand Down Expand Up @@ -176,6 +198,29 @@ __Z_INLINE void handleGetKeys(volatile uint32_t *flags, volatile uint32_t *tx, u
THROW(APDU_CODE_OK);
}

__Z_INLINE void handleComputeMaspRand(__Z_UNUSED volatile uint32_t *flags, volatile uint32_t *tx, __Z_UNUSED uint32_t rx, masp_type_e type) {
*tx = 0;
zxerr_t zxerr = app_fill_randomness(type);
if (zxerr != zxerr_ok) {
*tx = 0;
THROW(APDU_CODE_DATA_INVALID);
}
*tx = cmdResponseLen;
THROW(APDU_CODE_OK);
}

__Z_INLINE void handleExtractSpendSign(__Z_UNUSED volatile uint32_t *flags, volatile uint32_t *tx, __Z_UNUSED uint32_t rx) {
*tx = 0;
zxerr_t zxerr = app_fill_spend_sig();

if (zxerr != zxerr_ok) {
*tx = 0;
THROW(APDU_CODE_DATA_INVALID);
}
*tx = cmdResponseLen;
THROW(APDU_CODE_OK);
}

__Z_INLINE void handle_getversion(__Z_UNUSED volatile uint32_t *flags, volatile uint32_t *tx)
{
G_io_apdu_buffer[0] = 0;
Expand Down Expand Up @@ -250,8 +295,37 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
break;
}

case INS_GET_SPEND_RAND: {
CHECK_PIN_VALIDATED()
handleComputeMaspRand(flags, tx, rx, spend);
break;
}

case INS_GET_OUTPUT_RAND: {
CHECK_PIN_VALIDATED()
handleComputeMaspRand(flags, tx, rx, output);
break;
}

case INS_GET_CONVERT_RAND: {
CHECK_PIN_VALIDATED()
handleComputeMaspRand(flags, tx, rx, convert);
break;
}

case INS_SIGN_MASP: {
CHECK_PIN_VALIDATED()
handleSignMasp(flags, tx, rx);
break;
}

case INS_EXTRACT_SPEND_SIGN: {
CHECK_PIN_VALIDATED()
handleExtractSpendSign(flags, tx, rx);
break;
}
#if defined(APP_TESTING)
case INS_TEST: {
case INS_TEST: {
handleTest(flags, tx, rx);
THROW(APDU_CODE_OK);
break;
Expand Down
Loading

0 comments on commit a27fed2

Please sign in to comment.