/* ******************************************************************************* * Java Card Bitcoin Hardware Wallet * (c) 2015 Ledger * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************* */ package com.ledger.wallet; import javacard.security.ECPrivateKey; import javacard.security.KeyAgreement; import javacard.security.KeyBuilder; import javacard.security.Key; import javacard.security.Signature; public class JCardSIMProprietaryAPI implements ProprietaryAPI { private Signature signature; private KeyAgreement keyAgreement; private ECPrivateKey privateKey; private byte ecAlgorithm; public JCardSIMProprietaryAPI() { try { keyAgreement = com.licel.jcardsim.extensions.security.KeyAgreement.getInstance(com.licel.jcardsim.extensions.security.KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY, false); signature = com.licel.jcardsim.extensions.security.Signature.getInstance(com.licel.jcardsim.extensions.security.Signature.ALG_ECDSA_SHA_256_RFC6979, false); } catch(Exception e) { } try { privateKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_EC_FP_256, false); ecAlgorithm = KeyBuilder.TYPE_EC_FP_PRIVATE_TRANSIENT_DESELECT; } catch(Exception e) { try { privateKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE_TRANSIENT_RESET, KeyBuilder.LENGTH_EC_FP_256, false); ecAlgorithm = KeyBuilder.TYPE_EC_FP_PRIVATE_TRANSIENT_RESET; } catch(Exception e1) { try { privateKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256, false); ecAlgorithm = KeyBuilder.TYPE_EC_FP_PRIVATE; } catch(Exception e2) { } } } if ((privateKey != null) && (ecAlgorithm == KeyBuilder.TYPE_EC_FP_PRIVATE)) { Secp256k1.setCommonCurveParameters(privateKey); } } @Override public boolean getUncompressedPublicPoint(byte[] privateKey, short privateKeyOffset, byte[] publicPoint, short publicPointOffset) { if ((privateKey != null) && (keyAgreement != null)) { try { if (ecAlgorithm != KeyBuilder.TYPE_EC_FP_PRIVATE) { Secp256k1.setCommonCurveParameters(this.privateKey); } this.privateKey.setS(privateKey, privateKeyOffset, (short)32); keyAgreement.init(this.privateKey); keyAgreement.generateSecret(Secp256k1.SECP256K1_G, (short)0, (short)Secp256k1.SECP256K1_G.length, publicPoint, publicPointOffset); return true; } catch(Exception e) { return false; } } else { return false; } } @Override public boolean hasHmacSHA512() { return false; } @Override public void hmacSHA512(Key key, byte[] in, short inBuffer, short inLength, byte[] out, short outOffset) { } @Override public boolean hasDeterministicECDSASHA256() { return true; } @Override public void signDeterministicECDSASHA256(Key key, byte[] in, short inBuffer, short inLength, byte[] out, short outOffset) { signature.init(key, Signature.MODE_SIGN); signature.sign(in, inBuffer, inLength, out, outOffset); } }