monero-project / monero

Monero: the secure, private, untraceable cryptocurrency
https://getmonero.org
Other
8.89k stars 3.1k forks source link

Ledger device: CLA_NOT_SUPPORTED (0x6e00) #9479

Open dotnetspec opened 1 week ago

dotnetspec commented 1 week ago

Hi, Versions: Ledger Live 2.85.1 LNX 2.2.4 Nano X E8DD

I'm using Ledger'shw-transport-webhidin a web app to communicate with an LNX device as a part of this bounty. I am attempting to use the code below to connect to the LNX:

import "core-js/actual";
import { listen } from "@ledgerhq/logs";
import TransportWebHID from "@ledgerhq/hw-transport-webhid";

export async function getMoneroAddress(app) {
  try {
    console.log("Attempting to get Monero address now...");

    // Request access to the Ledger device
    const transport = await TransportWebHID.create();

    // Define APDU command parameters
    const cla = 0xe0; // Class byte for Ledger Monero app
    const ins = 0x46; // INS_DERIVE_SUBADDRESS_PUBLIC_KEY
    const p1 = 0x00; // First parameter
    const p2 = 0x00; // Second parameter

    // Derivation path: 44'/128'/0'/0/0
    const derivationPath = [
      0x8000002c, // 44'
      0x80000080, // 128'
      0x80000000, // 0'
      0x00000000, // 0
      0x00000000, // 0
    ];
    const data = serializeDerivationPath(derivationPath);

    console.log("Serialized Derivation Path:", data);

    // Send the APDU command to the Ledger device
    const response = await transport.send(cla, ins, p1, p2, data);

    // Listen to Ledger logs for debugging
    listen((log) => console.log(log));
    //console.log("Monero Address Response:", response);
    if (response.length > 2) {
      const statusCode = response.slice(-2); // Last 2 bytes are the status word
      if (statusCode[0] === 0x90 && statusCode[1] === 0x00) {
        console.log("Success:", response);
      } else {
        console.error("Error with status code:", statusCode);
      }
    }
  } catch (error) {
    console.error("Error getting Monero address:", error);
  }
}

// Helper function to serialize the derivation path
function serializeDerivationPath(path) {
  const buffer = new ArrayBuffer(1 + path.length * 4); // 1 byte for path length + 4 bytes for each path element
  const dataView = new DataView(buffer);
  dataView.setUint8(0, path.length); // First byte: path length

  path.forEach((element, index) => {
    dataView.setUint32(1 + index * 4, element);
  });

  return new Uint8Array(buffer);
}

function serializeDerivationPath()and associated data were generated by AI, so I am unable to confirm it's correctness myself. If it is wrong and/or there is a better alternative, please let me know.

Assuming it is correct (I get no errors directly relating to it), I have been applying the device codes listed in this file, but without success so far. I do not know what the CLA setting should be if not 0xe0 or 0xE0? I have tried a number of alternatives without success.

My understanding is that there are some general CLA values across different Ledger apps:

0x80: This is often used in Bitcoin-related apps.
0xB0: Common for Ethereum-related Ledger apps.
0xE0: Frequently used for Monero and other cryptocurrencies.
0xA0: Sometimes used for administrative commands.

but I consistently get 0x6E00: CLA not supported. as an error response whatever I try.

The Monero wallet is always open on the LNX when I try the commands through the web browser.

What is the correct value for the CLA? Is there anything else I could/should be doing to resolve the issue? thanks ...

dotnetspec commented 5 days ago

Steps to reproduce:

TransportStatusError: Ledger device: CLA_NOT_SUPPORTED (0x6e00)