GithubHelp home page GithubHelp logo

toporin / satochipapplet Goto Github PK

View Code? Open in Web Editor NEW
110.0 21.0 39.0 3.46 MB

The open source hardware wallet smartcard - Satochip.io

Home Page: https://satochip.io/shop

License: GNU Affero General Public License v3.0

Java 100.00%
bitcoin hardwarewallet cryptocurrency ethereum smartcard javacard nfc bip32

satochipapplet's Introduction

SatochipApplet

Open source javacard applet implementing a crypto-currency hardware wallet with full BIP32/BIP39 support.

Demonstration

demonstrationon youtube

Introduction

Satochip stands for Secure Anonymous Trustless and Open Chip. It is a javacard applet that can be used as a secure hardware wallet running for example on a Yubikey Neo. The Satochip applet has full BIP32/BIP39 supports.

Using Satochip, an initial BIP32 seed is imported in the javacard and private keys are derived as requested by an external application. Private keys are never exported outside of the secure chip. To improve performances, the result of key derivation is cached in secure memory for future requests so that a specific derivation path is only computed once.

The Satochip also supports the import of regular (non-BIP32 keys) such as vanity keys. Here again, private keys cannot be exported outside of the secure chip. Up to 16 regular keys can be imported on the chip. In any case, the private keys can be used to sign transactions and Bitcoin messages, if sufficient credentials are provided.

Access to private keys (creation, derivation and signature) is enforced through the use of PIN code (from 4 to 16 chars).

This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.

Advantages:

  • Code is free and open source (no NDA required);
  • Code is easy to read and maintain (javacard is a subset of java);
  • Multiple form factor could be supported in addition to Yubikey (e.g sim cards);
  • Plug and play;
  • Smartcards have a long experience in dealing with security and physical security in particular;
  • Can be easily used or extended for other crypto-currencies;
  • A test package is run during build to ensure that critical functionalities are implemented correctly.

Also, if used with a Yubikey:

  • Yubikey has minimal size and is practically indestructible;
  • The Yubico company is not going anywhere anytime soon;
  • Many promising functionalities: NFC, Yubikey OTP, U2F, ...;
  • Possibility to use the HMAC-SHA1 challenge-response of the Yubikey as second factor for additional security against malwares.

Disadvantages:

  • Building the applet might be a bit tricky;
  • The software implementation of HMAC-SHA512 could have an potential impact on the physical security against side-channel attacks (for attackers with physical access to the chip).

Supported hardware

To support Bitcoin signatures, the javacard must support ALG_ECDSA_SHA_256, which in practice requires a javacard compliant with the JavaCard 3.0.1 specification. Note that this is a necessary but not sufficient condition since javacards typically implements only a subset of the specification. A detailed list of javacard and their supported features is available here.

An interesting guide to consult before shopping can be found here.

Tested and working

Yubikey Neo

Important remark: the Yubikeys currently sold by Yubico are configured for production only and it is not possible to load the applet on these dongles (see this link for more details). Only the development Yubikeys (with serial number below 3,000,000) are suitable for our use!

NXP JCOP J2D081

Available for purchase here. (MOQ: 5 pieces).

Swissbit PS-100u VE card Secure micro SD memory card

More info here (Note however that Swissbit does not sell its product directly to end users but only to business partners).

J3D081 JCOP v2.4.2 R2

Available for purchase here. (MOQ: 1 piece).

Buidl

You can build the javacard CAP files or use the lastest built version.

To generate the CAP file from the sources, you can use the Eclipse IDE with the ant-javacard Ant task (see the instruction on the ant-javacard github repository).

Install

Once you have a CAP file, you have to download it on the chip card. You can use GlobalPlatformPro to do this:

  • Download the latest release from https://github.com/martinpaljak/GlobalPlatformPro/releases
  • (Put the CAP file in the same folder as the GPJ jar file for convenience)
  • To list the applets loaded on a smartcard: gp.exe -l
  • To load the SatoChip applet: gp.exe -install .\SatoChip-0.12-05.cap
  • To delete the SatoChip applet: gp.exe -uninstall .\SatoChip-0.12-05.cap

A more detailed tutorial is available on the GlobalPlatformPro repository.

Use

To use the applet, you have to connect your client application to the smartcard and send command APDU. These commands will be processed by the smartcard who will then send a response APDU.

Supported software clients

  • Bitcoin: the Bitcoin Electrum-Satochip is a version of Electrum that was slightly modified to integrate the Satochip hardware wallet.

  • Litecoin: the Litecoin Electrum-Satochip is a version of Electrum for Litecoin that was slightly modified to integrate the Satochip hardware wallet.

  • Bitcoin Cash: the Electron Cash-Satochip is a version of Electron Cash that was slightly modified to integrate the Satochip hardware wallet. Note: Satochip is natively supported by Electron Cash, we strongly encourage you to download the client from the official website.

  • eCash (XEC): Satochip is natively supported by Electrum ABC, we strongly encourage you to download the client from the official website.

  • Metamask: you can use your Satochip hardware wallet with a forked version of Metamask called Satomask. To allow the communication between the card and your web browser, you will need the Satochip Bridge.

  • MyEtherWallet: you can use your Satochip hardware wallet with a forked version of MyEtherWallet called MEW Satochip. To allow the communication between the card and your web browser, you will need the Satochip Bridge.

Deprecated (use older releases for this)

SatoChipClient is a small java library that allows to easily interface the SatoChip applet to your application through a simple set of API. An example of application is the BitcoinWallet java application, that uses SatoChipClient through another Bitcoin library called BitcoinCore.

Credits

License

This application is distributed under the GNU Affero General Public License version 3.

Some parts of the code may be licensed under a different (MIT-like) license. Contact us if you feel that some license combination is inappropriate.

satochipapplet's People

Contributors

alcofribas4 avatar bastien-satochip avatar toporin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

satochipapplet's Issues

Code compilation issues (and such)

Hello, when compiling the cap file using ant, I get one error (error: org.satochip.applet.CardEdge: unsupported int type of intermediate value, must cast intermediate value to type short or byte) - the culprits are:

offset++;
if (bytesLeft!=/*here*/(short)(5+altcoinSize))
	ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
recvBuffer[0]= (byte) (altcoinSize+17);

and

if ((bip32_depth < 0) || (bip32_depth > MAX_BIP32_DEPTH) )
        ISOException.throwIt(SW_INCORRECT_P1);
if (bytesLeft < /*here*/(short)(4*bip32_depth))
	ISOException.throwIt(SW_INVALID_PARAMETER);

// P2 option flags

Also, when searching for missing short casts, I noticed there are some lines that make no sense, would be nice to comment them out... though it looks more like bug to me

RFU = buffer[base++]; //create_object_ACL deprecated => RFU
RFU = buffer[base++]; //create_key_ACL deprecated => RFU
RFU = buffer[base++]; //create_pin_ACL deprecated => RFU

you are rewriting the value of unused RFU (it is not accessed afterwards) variable, yet increasing the value in the base variable.

Just reporting what I was forced to find out, hope it will be useful :) All the lines are from the Applet class file CardEdge.java

Unknown error in get_status() (error code 0x6c0c)

Electrum Satochip Version: electrum-satochip-v4.1.5
SatopchipApplet Version: SatoChip-0.12-05.cap
Card Type: THD-89 (Proprietary JCOS)

Issue:
Getting 'Failed to create a client for this device. Make sure it is in the correct state.' error message when trying to create a new hardware wallet with Satochip applet and Electrum client.

Trace Log:

20211204T095959.036948Z |     INFO | plugin.DeviceMgr | Registering <SatochipClient TODO>
20211204T095959.169798Z |     INFO | pysatochip.CardConnector | +Inserted: 3B 1B 96 50 6F 6C 61 72 69 73 20 21 01 11
20211204T100000.446336Z |    DEBUG | pysatochip.CardConnector | In card_select
20211204T100000.446336Z |    DEBUG | pysatochip.CardConnector | In card_transmit
20211204T100000.446336Z |    DEBUG | pysatochip.CardConnector | > 00 A4 04 00 08 53 61 74 6F 43 68 69 70
20211204T100000.460175Z |    DEBUG | pysatochip.CardConnector | < [] 90 00
20211204T100000.460582Z |    DEBUG | pysatochip.CardConnector | Found a Satochip!
20211204T100000.460582Z |    DEBUG | pysatochip.CardConnector | In card_get_status
20211204T100000.460582Z |    DEBUG | pysatochip.CardConnector | In card_transmit
20211204T100000.460582Z |    DEBUG | pysatochip.CardConnector | > B0 3C 00 00
20211204T100000.466263Z |    DEBUG | pysatochip.CardConnector | < [] 6C 0C
20211204T100000.466263Z |  WARNING | pysatochip.CardConnector | Unknown error in get_status() (error code 0x6c0c)
20211204T100000.467263Z |    DEBUG | pysatochip.CardConnector | In card_disconnect()
20211204T100000.467263Z |     INFO | pysatochip.CardConnector | disconnecting from'ExcelSecu Contact_Rd 0'
20211204T100000.510724Z |     INFO | plugins.satochip.satochip | [SatochipClient] client request: update_status
20211204T100000.510724Z |     INFO | plugins.satochip.satochip | [SatochipClient] self.handler is None! 
20211204T100001.944041Z |     INFO | plugins.satochip.satochip | [SatochipPlugin] setup_device()
20211204T100001.944041Z |     INFO | plugin.DeviceMgr | scanning devices...
20211204T100001.959304Z |     INFO | plugins.satochip.satochip | [SatochipPlugin] detect_smartcard_reader
20211204T100012.066339Z |     INFO | plugins.satochip.satochip | has_usable_connection_with_device()
20211204T100012.066339Z |    DEBUG | pysatochip.CardConnector | In card_get_ATR()
20211204T100012.066339Z |    ERROR | plugins.satochip.satochip | Exception in has_usable_connection_with_device: 'NoneType' object has no attribute 'connection'
Traceback (most recent call last):

Comments:
It seems that the GET_STATUS instruction is returning SW 0x6C0C. I am wondering if some card types are sensitive to Le being used and the current CardConnector does not issue a Le in the APDU.

A suggestion is to issue Le with 255 for all APDU commands which may help to accommodate more types of cards to run Electrum-Satochip by default.

Here's a GP.EXE execution with APDU with Le enabled:

>java -jar gp-old.jar -a 00A40400085361746F43686970 -a B03C000011 --debug
GlobalPlatformPro v20.01.23-0-g5ad373b
Running on Windows 10 10.0 amd64, Java 16.0.2 by Oracle Corporation
# Detected readers from JNA2PCSC
[*] ExcelSecu Contact_Rd 0
SCardConnect("ExcelSecu Contact_Rd 0", T=*) -> T=0, 3B1B96506F6C6172697320210111
SCardBeginTransaction("ExcelSecu Contact_Rd 0")
A>> T=0 (4+0008) 00A40400 08 5361746F43686970
A<< (0000+2) (15ms) 9000
A>> T=0 (4+0000) B03C0000 11
A<< (0012+2) (16ms) 000C00050000000000000001 9000
A>> T=0 (4+0000) 00A40400 00
A<< (0093+2) (32ms) 6F5B8408A000000003000000A54F734906072A864886FC6B01600B06092A864886FC6B020202630906072A864886FC6B03640B06092A864886FC6B040255650B06092A864886FC6B020101660C060A2B060104012A026E01029F6501FF 9000
[TRACE] GPSession -  [6F]
[TRACE] GPSession -      [84] A000000003000000
[TRACE] GPSession -      [A5]
[TRACE] GPSession -          [73]
[TRACE] GPSession -              [06] 2A864886FC6B01
[TRACE] GPSession -              [60]
[TRACE] GPSession -                  [06] 2A864886FC6B020202
[TRACE] GPSession -              [63]
[TRACE] GPSession -                  [06] 2A864886FC6B03
[TRACE] GPSession -              [64]
[TRACE] GPSession -                  [06] 2A864886FC6B040255
[TRACE] GPSession -              [65]
[TRACE] GPSession -                  [06] 2A864886FC6B020101
[TRACE] GPSession -              [66]
[TRACE] GPSession -                  [06] 2B060104012A026E0102
[TRACE] GPSession -          [9F65] FF
[DEBUG] GPSession - Auto-detected ISD: A000000003000000
SCardEndTransaction("ExcelSecu Contact_Rd 0")
SCardDisconnect("ExcelSecu Contact_Rd 0", true) tx:23/rx:111

Here's a GP.EXE execution with APDU with Le not enabled:

java -jar gp-old.jar -a 00A40400085361746F43686970 -a B03C0000 --debug
GlobalPlatformPro v20.01.23-0-g5ad373b
Running on Windows 10 10.0 amd64, Java 16.0.2 by Oracle Corporation
# Detected readers from JNA2PCSC
[*] ExcelSecu Contact_Rd 0
SCardConnect("ExcelSecu Contact_Rd 0", T=*) -> T=0, 3B1B96506F6C6172697320210111
SCardBeginTransaction("ExcelSecu Contact_Rd 0")
A>> T=0 (4+0008) 00A40400 08 5361746F43686970
A<< (0000+2) (15ms) 9000
A>> T=0 (4+0000) B03C0000
A<< (0000+2) (16ms) 9C11
A>> T=0 (4+0000) 00A40400 00
A<< (0093+2) (31ms) 6F5B8408A000000003000000A54F734906072A864886FC6B01600B06092A864886FC6B020202630906072A864886FC6B03640B06092A864886FC6B040255650B06092A864886FC6B020101660C060A2B060104012A026E01029F6501FF 9000
[TRACE] GPSession -  [6F]
[TRACE] GPSession -      [84] A000000003000000
[TRACE] GPSession -      [A5]
[TRACE] GPSession -          [73]
[TRACE] GPSession -              [06] 2A864886FC6B01
[TRACE] GPSession -              [60]
[TRACE] GPSession -                  [06] 2A864886FC6B020202
[TRACE] GPSession -              [63]
[TRACE] GPSession -                  [06] 2A864886FC6B03
[TRACE] GPSession -              [64]
[TRACE] GPSession -                  [06] 2A864886FC6B040255
[TRACE] GPSession -              [65]
[TRACE] GPSession -                  [06] 2A864886FC6B020101
[TRACE] GPSession -              [66]
[TRACE] GPSession -                  [06] 2B060104012A026E0102
[TRACE] GPSession -          [9F65] FF
[DEBUG] GPSession - Auto-detected ISD: A000000003000000
SCardEndTransaction("ExcelSecu Contact_Rd 0")
SCardDisconnect("ExcelSecu Contact_Rd 0", true) tx:22/rx:99

It seems the pysatochip.CardConnector getting SW 0x6C0C is abit odd since without Le, GP.EXE returns SW 0x9C11 and pysatochip.CardConnector on the other hand returns 0x6C0C.

There seems to be some differences in how GP.EXE and pysatochip.CardConnector calls the smartcards ?

Compatibility with JC30M48CR

Tried to test the applet with Infineon JC30M48CR, details about the card here:
https://github.com/crocs-muni/JCAlgTest/blob/master/Profiles/results/JavaCardOS_Infineon_JC30M48CR_ALGSUPPORT__3b_80_80_01_01_(provided_by_JavaCardOS_and_Thotheolh_Tay).csv

Cap was loaded successfully, and electron cash recognized the hardware wallet, however when I tried to initialize it, I got the error "Unable to setup the device with error code:0x6f 0x0".

Does this mean that this particular java card is not supported? Is it possible to know why? I see that it supports ALG_ECDSA_SHA_256 algorithm.

APDU command

Could you please provide the APDU command document? Or other ways to find the APDU command?

ImportKey method has non-standard behaviour

The problem is in the following code snippet:

if (key_size != LENGTH_EC_FP_256)
    ISOException.throwIt(key_size);

This is non-standard behavior that violates ISO7816. For instance, when I send the following APDU to the card, the response will be 9000 (= command correct). However, this command is invalid (wrong length).

B03200002C000C900000000000000000201111111111111111111111111111111111111111111111111111111111111111

Wrong behavior on spurious Select

When selecting an non-installed AID on a card, after selecting this applet, the applet returns NoError/0x9000 to this command. This confuses some systems as this indicates this selected AID is present and was selected, but it is actually not.

Communication Log
This card has the Satochip applet (5361746F4368697000), and nothing else.

 Sending 0xA4 command with 9 bytes data
  with Le=256
-> 00 A4 04 00 09 53 61 74 6F 43 68 69 70 00 00
 Received 0 bytes data : SW 0x9000 - 23.4 ms
 Sending 0xA4 command with 16 bytes data
  with Le=256
-> 00 A4 04 00 10 FF 4C 45 47 52 2E 57 41 4C 54 30 31 2E 49 30 31 00
 Received 0 bytes data : SW 0x9000 - 8.9 ms

This indicates the selection of the last AID was performed successfully. But in fact, the card keeps the same Satochip applet selected, and there's no such AID available on the card.

The practical issue is with the Uniblow wallet. When a user selects a device, it tries to connect to all card readers and if there's a card, it selects the specific AID. If the Select response is OK, it assumes it has found the chosen device, and it marks the device as available and connected. If a user has a Satochip connected, selects the Satochip applet, then selects an other smartcard-based device, the wallet mistakes the Satochip for this other device. Because the Satochip replies OK for this other AID selection. So Uniblow thinks it has found the other device. Then the following command to this -wrong- device returns CLANotSupported/0x6E00, and that leads to an uncaught exception which is displayed to the user "Error : 6E00".

In internal details, the JavaCard runtime routes any Select command with an unknown AID to the current applet. That is called spurious select. When sending a select for a not-installed applet, the JC system calls the process method of the currently selected applet. So this applet is responsible to process this Select command. An application, whether explicitly or implicitly selected, is responsible for correctly managing spurious SELECT commands. The selectingApplet() method returns false, so the application must first determine if it has knowledge on how to handle the particular SELECT command, else it must return an error.

The fact that the AID doesn't not exist, and the select command was not performed must be stated by the Satochip applet by answering an error status (not 0x9000). There are several possibilities to change the 9000 behavior :

  • Return CLANotSupported/0x6E00, I think this is the case by just removing the "match select" block that returns.
  • Return INSNotSupported/0x6D00, stated that Select is not a supported command.
  • Return FileNotFound/0x6A82, the default status code when the card system can't find the requested applet id.

The culprit is here

// check SELECT APDU command

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.