Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for hf 15 (view tags) #110

Merged
merged 11 commits into from
Jul 27, 2022
10 changes: 9 additions & 1 deletion .github/workflows/lint-workflow.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
name: Code style check

on: [push, pull_request]
on:
push:
branches:
- master
- develop
pull_request:
branches:
- master
- develop

jobs:
job_lint:
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ endif
#DEFINES += MONERO_BETA

APPVERSION_M=1
APPVERSION_N=7
APPVERSION_P=8
APPVERSION_N=8
APPVERSION_P=0

APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
SPECVERSION="1.0"
Expand Down
51 changes: 51 additions & 0 deletions doc/developer/blue-app-commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@
.. |eDRVout| replace:: :math:`\widetilde{\mathfrak{D}_\mathrm{out}}`
.. |AKout| replace:: :math:`\mathcal{AK}_\mathrm{amount}`
.. |eAKout| replace:: :math:`\widetilde{\mathcal{AK}_\mathrm{amount}}`
.. |vtf| replace:: :math:`\mathit{view_tag_full}`
.. |vt| replace:: :math:`\mathit{view_tag}`


.. |ctH| replace:: :math:`\mathcal{H}_\mathrm{commitment}`
Expand Down Expand Up @@ -198,6 +200,7 @@ To summarize, the signature process is:

- compute the range proof
- blind the amount
- compute the view tag

. Compute the final confidential ring signature

Expand Down Expand Up @@ -1142,6 +1145,54 @@ return |Img|.
+--------+-----------------------------------------------------------------+


Derive View Tag
~~~~~~~~~~~~~~~~~~

**Monero**

crypto::derive_view_tag.

**Description**

Derive the view tag of an output.

| compute |Drv| = |dec|[|spk|](|eDrv|)
| compute |vtf| = |Hs|("view_tag" \|, |Drv|, |idx|)
| compute |vt| = |vtf|[0:1]

return |vt|.

**Command**

+-----+-----+-----+-----+----------+
| CLA | INS | P1 | P2 | LC |
+=====+=====+=====+=====+==========+
| 03 | 3B | 00 | 00 | 25 or 45 |
+-----+-----+-----+-----+----------+

**Command data**

+--------+-----------------------------------------------------------------+
| Length | Value |
+========+=================================================================+
| 01 | 00 |
+--------+-----------------------------------------------------------------+
| 20 | encrypted key derivation |eDrv| |
+--------+-----------------------------------------------------------------+
| 20 | ephemeral hmac (optional, only during active transaction) |
+--------+-----------------------------------------------------------------+
| 04 | index |
+--------+-----------------------------------------------------------------+

**Response data**

+--------+-----------------------------------------------------------------+
| Length | Value |
+========+=================================================================+
| 01 | view tag |vt| |
+--------+-----------------------------------------------------------------+


Generate Keypair
~~~~~~~~~~~~~~~~

Expand Down
2 changes: 2 additions & 0 deletions src/monero_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ int monero_apdu_derivation_to_scalar(void);
int monero_apdu_derive_public_key(void);
int monero_apdu_derive_secret_key(void);
int monero_apdu_generate_key_image(void);
int monero_apdu_derive_view_tag(void);
int monero_apdu_derive_subaddress_public_key(void);
int monero_apdu_get_subaddress(void);
int monero_apdu_get_subaddress_spend_public_key(void);
Expand Down Expand Up @@ -169,6 +170,7 @@ void monero_derive_public_key(unsigned char *x, unsigned char *drv_data, unsigne
unsigned char *ec_pub);
void monero_secret_key_to_public_key(unsigned char *ec_pub, unsigned char *ec_priv);
void monero_generate_key_image(unsigned char *img, unsigned char *P, unsigned char *x);
void monero_derive_view_tag(unsigned char *view_tag, unsigned char *drv_data, unsigned int out_idx);

void monero_derive_subaddress_public_key(unsigned char *x, unsigned char *pub,
unsigned char *drv_data, unsigned int index);
Expand Down
16 changes: 16 additions & 0 deletions src/monero_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,22 @@ void monero_generate_key_image(unsigned char *img, unsigned char *P, unsigned ch
monero_ecmul_k(img, I, x);
}

/* ----------------------------------------------------------------------- */
/* --- --- */
/* ----------------------------------------------------------------------- */
void monero_derive_view_tag(unsigned char *view_tag, unsigned char *drv_data,
unsigned int out_idx) {
unsigned char varint[8 + 32 + 8];
unsigned int len_varint;

os_memmove(varint, "view_tag", 8);
os_memmove(varint + 8, drv_data, 32);
len_varint = monero_encode_varint(varint + 8 + 32, 8, out_idx);
len_varint += 8 + 32;
monero_keccak_F(varint, len_varint, varint);
os_memmove(view_tag, varint, 1);
}

/* ======================================================================= */
/* SUB ADDRESS */
/* ======================================================================= */
Expand Down
4 changes: 4 additions & 0 deletions src/monero_dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ int check_ins_access() {
case INS_DERIVE_PUBLIC_KEY:
case INS_DERIVE_SECRET_KEY:
case INS_GEN_KEY_IMAGE:
case INS_DERIVE_VIEW_TAG:
case INS_SECRET_KEY_TO_PUBLIC_KEY:
case INS_SECRET_KEY_ADD:
case INS_GENERATE_KEYPAIR:
Expand Down Expand Up @@ -188,6 +189,9 @@ int monero_dispatch() {
case INS_GEN_KEY_IMAGE:
sw = monero_apdu_generate_key_image();
break;
case INS_DERIVE_VIEW_TAG:
sw = monero_apdu_derive_view_tag();
break;
case INS_SECRET_KEY_ADD:
sw = monero_apdu_sc_add();
break;
Expand Down
45 changes: 29 additions & 16 deletions src/monero_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,32 +177,45 @@ void monero_install(unsigned char netId) {
/* ----------------------------------------------------------------------- */
/* --- Reset --- */
/* ----------------------------------------------------------------------- */
const char* const monero_supported_client[] = {"0.17.0.", "0.17.1.", "0.17.2.", "0.17.3."};
#define MONERO_SUPPORTED_CLIENT_SIZE \
(sizeof(monero_supported_client) / sizeof(monero_supported_client[0]))
// Accept the following versions and their derivates
const char* const supported_clients[] = {"0.18."};
#define MONERO_SUPPORTED_CLIENT_SIZE (sizeof(supported_clients) / sizeof(supported_clients[0]))

// Explicitly refuse the following versions
const char* const refused_clients[] = {"0.18.0.0."};
#define MONERO_REFUSED_CLIENT_SIZE (sizeof(refused_clients) / sizeof(refused_clients[0]))

static bool is_client_version_valid(const char* client_version) {
// Check if version is explicitly refused
for (uint32_t i = 0; i < MONERO_REFUSED_CLIENT_SIZE; ++i) {
if (strcmp(PIC(refused_clients[i]), client_version) == 0) {
return false;
}
}
// Check if version is supported
for (uint32_t i = 0; i < MONERO_SUPPORTED_CLIENT_SIZE; ++i) {
// Use strncmp to allow supported version prefixing client version
unsigned int supported_clients_len = strlen(PIC(supported_clients[i]));
if (strncmp(PIC(supported_clients[i]), client_version, supported_clients_len) == 0) {
return true;
}
}
return false;
}

int monero_apdu_reset() {
unsigned int client_version_len;
char client_version[16];
memset(client_version, '\0', 16);
client_version_len = G_monero_vstate.io_length - G_monero_vstate.io_offset;
if (client_version_len > 14) {
THROW(SW_CLIENT_NOT_SUPPORTED + 1);
}
monero_io_fetch((unsigned char*)&client_version[0], client_version_len);
// Add '.' suffix to avoid 'X.1' prefixing 'X.10'
client_version[client_version_len] = '.';
client_version_len++;
client_version[client_version_len] = 0;
unsigned int i = 0;
while (i < MONERO_SUPPORTED_CLIENT_SIZE) {
unsigned int monero_supported_client_len = strlen((char*)PIC(monero_supported_client[i]));
if ((monero_supported_client_len <= client_version_len) &&
(os_memcmp((char*)PIC(monero_supported_client[i]), client_version,
monero_supported_client_len) == 0)) {
break;
}
i++;
}
if (i == MONERO_SUPPORTED_CLIENT_SIZE) {

if (!is_client_version_valid(client_version)) {
THROW(SW_CLIENT_NOT_SUPPORTED);
}

Expand Down
34 changes: 33 additions & 1 deletion src/monero_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,27 @@ int monero_apdu_generate_key_image(
return SW_OK;
}

/* ----------------------------------------------------------------------- */
/* --- --- */
/* ----------------------------------------------------------------------- */
int monero_apdu_derive_view_tag(
/*const crypto::key_derivation &derivation, const size_t output_index, crypto::view_tag &view_tag*/) {
unsigned char derivation[32];
unsigned int output_index;
unsigned char res[1];

// fetch
monero_io_fetch_decrypt(derivation, 32, TYPE_DERIVATION);
output_index = monero_io_fetch_u32();
monero_io_discard(0);

// derive and keep
monero_derive_view_tag(res, derivation, output_index);

monero_io_insert(res, 1);
return SW_OK;
}

/* ----------------------------------------------------------------------- */
/* --- --- */
/* ----------------------------------------------------------------------- */
Expand Down Expand Up @@ -692,7 +713,7 @@ int monero_apdu_get_subaddress_secret_key(/*const crypto::secret_key& sec, const
/* --- --- */
/* ----------------------------------------------------------------------- */

int monero_apu_generate_txout_keys(/*size_t tx_version, crypto::secret_key tx_sec, crypto::public_key Aout, crypto::public_key Bout, size_t output_index, bool is_change, bool is_subaddress, bool need_additional_key*/) {
int monero_apu_generate_txout_keys(/*size_t tx_version, crypto::secret_key tx_sec, crypto::public_key Aout, crypto::public_key Bout, size_t output_index, bool is_change, bool is_subaddress, bool need_additional_key, bool use_view_tags*/) {
// IN
unsigned int tx_version;
unsigned char tx_key[32];
Expand All @@ -704,10 +725,12 @@ int monero_apu_generate_txout_keys(/*size_t tx_version, crypto::secret_key tx_se
unsigned char is_subaddress;
unsigned char need_additional_txkeys;
unsigned char additional_txkey_sec[32];
unsigned char use_view_tags;
// OUT
unsigned char additional_txkey_pub[32];
#define amount_key tx_key
#define out_eph_public_key additional_txkey_sec
unsigned char view_tag[1];
// TMP
unsigned char derivation[32];

Expand All @@ -728,6 +751,7 @@ int monero_apu_generate_txout_keys(/*size_t tx_version, crypto::secret_key tx_se
} else {
monero_io_fetch(NULL, 32);
}
use_view_tags = monero_io_fetch_u8();

// update outkeys hash control
if (G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL) {
Expand Down Expand Up @@ -769,13 +793,21 @@ int monero_apu_generate_txout_keys(/*size_t tx_version, crypto::secret_key tx_se
// compute ephemeral output key
monero_derive_public_key(out_eph_public_key, derivation, output_index, Bout);

// compute view tag
if (use_view_tags) {
monero_derive_view_tag(view_tag, derivation, output_index);
}

// send all
monero_io_discard(0);
monero_io_insert_encrypt(amount_key, 32, TYPE_AMOUNT_KEY);
monero_io_insert(out_eph_public_key, 32);
if (need_additional_txkeys) {
monero_io_insert(additional_txkey_pub, 32);
}
if (use_view_tags) {
monero_io_insert(view_tag, 1);
}
G_monero_vstate.tx_output_cnt++;
return SW_OK;
}
1 change: 1 addition & 0 deletions src/monero_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ typedef struct monero_v_state_s monero_v_state_t;
#define INS_DERIVE_PUBLIC_KEY 0x36
#define INS_DERIVE_SECRET_KEY 0x38
#define INS_GEN_KEY_IMAGE 0x3A
#define INS_DERIVE_VIEW_TAG 0x3B
#define INS_SECRET_KEY_ADD 0x3C
#define INS_GENERATE_KEYPAIR 0x40
#define INS_SECRET_SCAL_MUL_KEY 0x42
Expand Down
1 change: 1 addition & 0 deletions tests/monero_client/monero_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def gen_txout_keys(self,
b"\x01" if is_change_addr else b"\x00",
b"\x01" if is_subaddress else b"\x00",
b"\x00" * 33, # additional_txkeys
b"\x00" * 33, # use_view_tags
))

self.device.send(cla=PROTOCOL_VERSION,
Expand Down
24 changes: 24 additions & 0 deletions tests/monero_client/monero_crypto_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,27 @@ def gen_key_derivation(self, pub_key: bytes, _priv_key: bytes) -> bytes:
assert len(response) == 32

return _d_in

def derive_view_tag(self, derivation: bytes, output_index: bytes) -> int:
ins: InsType = InsType.INS_DERIVE_VIEW_TAG

payload: bytes = b"".join([
derivation,
output_index,
])

self.device.send(cla=PROTOCOL_VERSION,
ins=ins,
p1=0,
p2=0,
option=0,
payload=payload)

sw, response = self.device.recv() # type: int, bytes

if not sw & 0x9000:
raise DeviceError(sw, ins)

assert len(response) == 1

return int.from_bytes(response, "big")
1 change: 1 addition & 0 deletions tests/monero_client/monero_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class InsType(enum.IntEnum):
INS_DERIVE_PUBLIC_KEY = 0x36
INS_DERIVE_SECRET_KEY = 0x38
INS_GEN_KEY_IMAGE = 0x3A
INS_DERIVE_VIEW_TAG = 0x3B
INS_SECRET_KEY_ADD = 0x3C
INS_GENERATE_KEYPAIR = 0x40
INS_SECRET_SCAL_MUL_KEY = 0x42
Expand Down
Loading