avoid non-primitive, non-final static references

This commit is contained in:
Michele Balistreri 2018-09-26 15:22:04 +02:00
parent 174675dba8
commit 3c5fd3bfca
4 changed files with 83 additions and 74 deletions

View File

@ -24,20 +24,17 @@ public class Crypto {
final static private byte[] KEY_BITCOIN_SEED = {'B', 'i', 't', 'c', 'o', 'i', 'n', ' ', 's', 'e', 'e', 'd'};
// The below 4 objects can be accessed anywhere from the entire applet
static RandomData random;
static KeyAgreement ecdh;
static MessageDigest sha256;
static MessageDigest sha512;
RandomData random;
KeyAgreement ecdh;
MessageDigest sha256;
MessageDigest sha512;
private static Signature hmacSHA512;
private static HMACKey hmacKey;
private Signature hmacSHA512;
private HMACKey hmacKey;
private static byte[] tmp;
private byte[] tmp;
/**
* Initializes the objects required by this class. Must be invoked exactly 1 time during application installation.
*/
static void init() {
Crypto() {
random = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
sha256 = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
ecdh = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH_PLAIN, false);
@ -70,7 +67,7 @@ public class Crypto {
* @param chainOff the offset in the chain code buffer
* @return true if successful, false otherwise
*/
static boolean bip32CKDPriv(byte[] i, short iOff, ECPrivateKey privateKey, ECPublicKey publicKey, byte[] chain, short chainOff) {
boolean bip32CKDPriv(byte[] i, short iOff, ECPrivateKey privateKey, ECPublicKey publicKey, byte[] chain, short chainOff) {
short off = 0;
if ((i[iOff] & (byte) 0x80) == (byte) 0x80) {
@ -113,8 +110,8 @@ public class Crypto {
* @param masterKey the output buffer
* @param keyOff the offset in the output buffer
*/
static void bip32MasterFromSeed(byte[] seed, short seedOff, short seedSize, byte[] masterKey, short keyOff) {
Crypto.hmacSHA512(KEY_BITCOIN_SEED, (short) 0, (short) KEY_BITCOIN_SEED.length, seed, seedOff, seedSize, masterKey, keyOff);
void bip32MasterFromSeed(byte[] seed, short seedOff, short seedSize, byte[] masterKey, short keyOff) {
hmacSHA512(KEY_BITCOIN_SEED, (short) 0, (short) KEY_BITCOIN_SEED.length, seed, seedOff, seedSize, masterKey, keyOff);
}
/**
@ -125,7 +122,7 @@ public class Crypto {
* @param off the offset
* @return the number of bytes by which the signature length changed
*/
static short fixS(byte[] sig, short off) {
short fixS(byte[] sig, short off) {
short sOff = (short) (sig[(short) (off + 3)] + (short) (off + 5));
short ret = 0;
@ -158,7 +155,7 @@ public class Crypto {
* @param out the output buffer
* @param outOff the offset in the output buffer
*/
private static void hmacSHA512(byte[] key, short keyOff, short keyLen, byte[] in, short inOff, short inLen, byte[] out, short outOff) {
private void hmacSHA512(byte[] key, short keyOff, short keyLen, byte[] in, short inOff, short inLen, byte[] out, short outOff) {
if (hmacSHA512 != null) {
hmacKey.setKey(key, keyOff, keyLen);
hmacSHA512.init(hmacKey, Signature.MODE_SIGN);
@ -174,9 +171,9 @@ public class Crypto {
sha512.update(tmp, HMAC_BLOCK_OFFSET, HMAC_BLOCK_SIZE);
if (i == 0) {
Crypto.sha512.doFinal(in, inOff, inLen, out, outOff);
sha512.doFinal(in, inOff, inLen, out, outOff);
} else {
Crypto.sha512.doFinal(out, outOff, HMAC_OUT_SIZE, out, outOff);
sha512.doFinal(out, outOff, HMAC_OUT_SIZE, out, outOff);
}
}
}
@ -194,7 +191,7 @@ public class Crypto {
* @param out the output buffer
* @param outOff the offset in the output buffer
*/
private static void addm256(byte[] a, short aOff, byte[] b, short bOff, byte[] n, short nOff, byte[] out, short outOff) {
private void addm256(byte[] a, short aOff, byte[] b, short bOff, byte[] n, short nOff, byte[] out, short outOff) {
if ((add256(a, aOff, b, bOff, out, outOff) != 0) || (ucmp256(out, outOff, n, nOff) > 0)) {
sub256(out, outOff, n, nOff, out, outOff);
}
@ -209,7 +206,7 @@ public class Crypto {
* @param bOff the offset of the b operand
* @return the comparison result
*/
private static short ucmp256(byte[] a, short aOff, byte[] b, short bOff) {
private short ucmp256(byte[] a, short aOff, byte[] b, short bOff) {
short ai, bi;
for (short i = 0 ; i < 32; i++) {
ai = (short)(a[(short)(aOff + i)] & 0x00ff);
@ -230,7 +227,7 @@ public class Crypto {
* @param aOff the offset of the a operand
* @return true if a is 0, false otherwise
*/
private static boolean isZero256(byte[] a, short aOff) {
private boolean isZero256(byte[] a, short aOff) {
boolean isZero = true;
for (short i = 0; i < (byte) 32; i++) {
@ -254,7 +251,7 @@ public class Crypto {
* @param outOff the offset in the output buffer
* @return the carry of the addition
*/
private static short add256(byte[] a, short aOff, byte[] b, short bOff, byte[] out, short outOff) {
private short add256(byte[] a, short aOff, byte[] b, short bOff, byte[] out, short outOff) {
short outI = 0;
for (short i = 31 ; i >= 0 ; i--) {
outI = (short) ((short)(a[(short)(aOff + i)] & 0xFF) + (short)(b[(short)(bOff + i)] & 0xFF) + outI);
@ -275,7 +272,7 @@ public class Crypto {
* @param outOff the offset in the output buffer
* @return the carry of the subtraction
*/
private static short sub256(byte[] a, short aOff, byte[] b, short bOff, byte[] out, short outOff) {
private short sub256(byte[] a, short aOff, byte[] b, short bOff, byte[] out, short outOff) {
short outI = 0;
for (short i = 31 ; i >= 0 ; i--) {

View File

@ -52,12 +52,15 @@ public class SECP256k1 {
private static final byte ALG_EC_SVDP_DH_PLAIN_XY = 6; // constant from JavaCard 3.0.5
private static KeyAgreement ecPointMultiplier;
private KeyAgreement ecPointMultiplier;
private Crypto crypto;
/**
* Allocates objects needed by this class. Must be invoked during the applet installation exactly 1 time.
*/
static void init() {
SECP256k1(Crypto crypto) {
this.crypto = crypto;
try {
ecPointMultiplier = KeyAgreement.getInstance(ALG_EC_SVDP_DH_PLAIN_XY, false);
} catch(CryptoException e) {
@ -70,7 +73,7 @@ public class SECP256k1 {
*
* @param key the key where the curve parameters must be set
*/
static void setCurveParameters(ECKey key) {
void setCurveParameters(ECKey key) {
key.setA(SECP256K1_A, (short) 0x00, (short) SECP256K1_A.length);
key.setB(SECP256K1_B, (short) 0x00, (short) SECP256K1_B.length);
key.setFieldFP(SECP256K1_FP, (short) 0x00, (short) SECP256K1_FP.length);
@ -88,7 +91,7 @@ public class SECP256k1 {
* @param pubOff the offset in pubOut
* @return the length of the public key
*/
static short derivePublicKey(ECPrivateKey privateKey, byte[] pubOut, short pubOff) {
short derivePublicKey(ECPrivateKey privateKey, byte[] pubOut, short pubOff) {
return multiplyPoint(privateKey, SECP256K1_G, (short) 0, (short) SECP256K1_G.length, pubOut, pubOff);
}
@ -102,9 +105,9 @@ public class SECP256k1 {
* @param xOff the offset in xOut
* @return the length of X
*/
static short derivePublicX(ECPrivateKey privateKey, byte[] xOut, short xOff) {
Crypto.ecdh.init(privateKey);
return Crypto.ecdh.generateSecret(SECP256K1_G, (short) 0, (short) SECP256K1_G.length, xOut, xOff);
short derivePublicX(ECPrivateKey privateKey, byte[] xOut, short xOff) {
crypto.ecdh.init(privateKey);
return crypto.ecdh.generateSecret(SECP256K1_G, (short) 0, (short) SECP256K1_G.length, xOut, xOff);
}
/**
@ -119,7 +122,7 @@ public class SECP256k1 {
* @param outOff the offset in the output buffer
* @return the length of the data written in the out buffer
*/
static short multiplyPoint(ECPrivateKey privateKey, byte[] point, short pointOff, short pointLen, byte[] out, short outOff) {
short multiplyPoint(ECPrivateKey privateKey, byte[] point, short pointOff, short pointLen, byte[] out, short outOff) {
assertECPointMultiplicationSupport();
ecPointMultiplier.init(privateKey);
return ecPointMultiplier.generateSecret(point, pointOff, pointLen, out, outOff);
@ -130,7 +133,7 @@ public class SECP256k1 {
*
* @return whether the card supports EC point multiplication or not
*/
static boolean hasECPointMultiplication() {
boolean hasECPointMultiplication() {
return ecPointMultiplier != null;
}
@ -138,7 +141,7 @@ public class SECP256k1 {
* Asserts that EC point multiplication is supported. If not, the 0x6A81 status word is returned by throwing an
* ISOException.
*/
static void assertECPointMultiplicationSupport() {
void assertECPointMultiplicationSupport() {
if(!hasECPointMultiplication()) {
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
}

View File

@ -44,11 +44,17 @@ public class SecureChannel {
private byte remainingSlots;
private boolean mutuallyAuthenticated = false;
private Crypto crypto;
private SECP256k1 secp256k1;
/**
* Instantiates a Secure Channel. All memory allocations needed for the secure channel are performed here. The keypair
* used for the EC-DH algorithm is also generated here.
*/
public SecureChannel(byte pairingLimit, byte[] aPairingSecret, short off) {
public SecureChannel(byte pairingLimit, byte[] aPairingSecret, short off, Crypto crypto, SECP256k1 secp256k1) {
this.crypto = crypto;
this.secp256k1 = secp256k1;
scCipher = Cipher.getInstance(Cipher.ALG_AES_CBC_ISO9797_M2,false);
try {
@ -62,8 +68,8 @@ public class SecureChannel {
scMacKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, false);
scKeypair = new KeyPair(KeyPair.ALG_EC_FP, SC_KEY_LENGTH);
SECP256k1.setCurveParameters((ECKey) scKeypair.getPrivate());
SECP256k1.setCurveParameters((ECKey) scKeypair.getPublic());
secp256k1.setCurveParameters((ECKey) scKeypair.getPrivate());
secp256k1.setCurveParameters((ECKey) scKeypair.getPublic());
scKeypair.genKeyPair();
secret = JCSystem.makeTransientByteArray((short)(SC_SECRET_LENGTH * 2), JCSystem.CLEAR_ON_DESELECT);
@ -93,20 +99,20 @@ public class SecureChannel {
pairingKeyOff++;
}
Crypto.ecdh.init(scKeypair.getPrivate());
crypto.ecdh.init(scKeypair.getPrivate());
short len;
try {
len = Crypto.ecdh.generateSecret(apduBuffer, ISO7816.OFFSET_CDATA, apduBuffer[ISO7816.OFFSET_LC], secret, (short) 0);
len = crypto.ecdh.generateSecret(apduBuffer, ISO7816.OFFSET_CDATA, apduBuffer[ISO7816.OFFSET_LC], secret, (short) 0);
} catch(Exception e) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return;
}
Crypto.random.generateData(apduBuffer, (short) 0, (short) (SC_SECRET_LENGTH + SC_BLOCK_SIZE));
Crypto.sha512.update(secret, (short) 0, len);
Crypto.sha512.update(pairingKeys, pairingKeyOff, SC_SECRET_LENGTH);
Crypto.sha512.doFinal(apduBuffer, (short) 0, SC_SECRET_LENGTH, secret, (short) 0);
crypto.random.generateData(apduBuffer, (short) 0, (short) (SC_SECRET_LENGTH + SC_BLOCK_SIZE));
crypto.sha512.update(secret, (short) 0, len);
crypto.sha512.update(pairingKeys, pairingKeyOff, SC_SECRET_LENGTH);
crypto.sha512.doFinal(apduBuffer, (short) 0, SC_SECRET_LENGTH, secret, (short) 0);
scEncKey.setKey(secret, (short) 0);
scMacKey.setKey(secret, SC_SECRET_LENGTH);
Util.arrayCopyNonAtomic(apduBuffer, SC_SECRET_LENGTH, secret, (short) 0, SC_BLOCK_SIZE);
@ -139,7 +145,7 @@ public class SecureChannel {
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
}
Crypto.random.generateData(apduBuffer, SC_OUT_OFFSET, SC_SECRET_LENGTH);
crypto.random.generateData(apduBuffer, SC_OUT_OFFSET, SC_SECRET_LENGTH);
respond(apdu, len, ISO7816.SW_NO_ERROR);
}
@ -195,9 +201,9 @@ public class SecureChannel {
ISOException.throwIt(ISO7816.SW_FILE_FULL);
}
Crypto.sha256.update(pairingSecret, (short) 0, SC_SECRET_LENGTH);
Crypto.sha256.doFinal(apduBuffer, ISO7816.OFFSET_CDATA, SC_SECRET_LENGTH, apduBuffer, (short) 0);
Crypto.random.generateData(secret, (short) 0, SC_SECRET_LENGTH);
crypto.sha256.update(pairingSecret, (short) 0, SC_SECRET_LENGTH);
crypto.sha256.doFinal(apduBuffer, ISO7816.OFFSET_CDATA, SC_SECRET_LENGTH, apduBuffer, (short) 0);
crypto.random.generateData(secret, (short) 0, SC_SECRET_LENGTH);
Util.arrayCopyNonAtomic(secret, (short) 0, apduBuffer, SC_SECRET_LENGTH, SC_SECRET_LENGTH);
return (SC_SECRET_LENGTH * 2);
@ -212,17 +218,17 @@ public class SecureChannel {
* @return the length of the reply
*/
private short pairStep2(byte[] apduBuffer) {
Crypto.sha256.update(pairingSecret, (short) 0, SC_SECRET_LENGTH);
Crypto.sha256.doFinal(secret, (short) 0, SC_SECRET_LENGTH, secret, (short) 0);
crypto.sha256.update(pairingSecret, (short) 0, SC_SECRET_LENGTH);
crypto.sha256.doFinal(secret, (short) 0, SC_SECRET_LENGTH, secret, (short) 0);
if (Util.arrayCompare(apduBuffer, ISO7816.OFFSET_CDATA, secret, (short) 0, SC_SECRET_LENGTH) != 0) {
preassignedPairingOffset = -1;
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
}
Crypto.random.generateData(apduBuffer, (short) 1, SC_SECRET_LENGTH);
Crypto.sha256.update(pairingSecret, (short) 0, SC_SECRET_LENGTH);
Crypto.sha256.doFinal(apduBuffer, (short) 1, SC_SECRET_LENGTH, pairingKeys, (short) (preassignedPairingOffset + 1));
crypto.random.generateData(apduBuffer, (short) 1, SC_SECRET_LENGTH);
crypto.sha256.update(pairingSecret, (short) 0, SC_SECRET_LENGTH);
crypto.sha256.doFinal(apduBuffer, (short) 1, SC_SECRET_LENGTH, pairingKeys, (short) (preassignedPairingOffset + 1));
pairingKeys[preassignedPairingOffset] = 1;
remainingSlots--;
apduBuffer[0] = (byte) (preassignedPairingOffset / PAIRING_KEY_LENGTH);

View File

@ -113,6 +113,9 @@ public class WalletApplet extends Applet {
private boolean signInProgress;
private boolean expectPublicKey;
private Crypto crypto;
private SECP256k1 secp256k1;
/**
* Invoked during applet installation. Creates an instance of this class. The installation parameters are passed in
* the given buffer.
@ -136,11 +139,11 @@ public class WalletApplet extends Applet {
* @param bLength length of the installation parameters
*/
public WalletApplet(byte[] bArray, short bOffset, byte bLength) {
Crypto.init();
SECP256k1.init();
crypto = new Crypto();
secp256k1 = new SECP256k1(crypto);
uid = new byte[UID_LENGTH];
Crypto.random.generateData(uid, (short) 0, UID_LENGTH);
crypto.random.generateData(uid, (short) 0, UID_LENGTH);
masterPublic = (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, EC_KEY_SIZE, false);
masterPrivate = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, EC_KEY_SIZE, false);
@ -157,22 +160,22 @@ public class WalletApplet extends Applet {
keyPath = new byte[KEY_PATH_MAX_DEPTH * 4];
pinlessPath = new byte[KEY_PATH_MAX_DEPTH * 4];
SECP256k1.setCurveParameters(masterPublic);
SECP256k1.setCurveParameters(masterPrivate);
secp256k1.setCurveParameters(masterPublic);
secp256k1.setCurveParameters(masterPrivate);
SECP256k1.setCurveParameters(parentPublicKey);
SECP256k1.setCurveParameters(parentPrivateKey);
secp256k1.setCurveParameters(parentPublicKey);
secp256k1.setCurveParameters(parentPrivateKey);
parentValid = false;
SECP256k1.setCurveParameters(publicKey);
SECP256k1.setCurveParameters(privateKey);
secp256k1.setCurveParameters(publicKey);
secp256k1.setCurveParameters(privateKey);
signature = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false);
short c9Off = (short)(bOffset + bArray[bOffset] + 1); // Skip AID
c9Off += (short)(bArray[c9Off] + 2); // Skip Privileges and parameter length
secureChannel = new SecureChannel(PAIRING_MAX_CLIENT_COUNT, bArray, (short) (c9Off + PUK_LENGTH));
secureChannel = new SecureChannel(PAIRING_MAX_CLIENT_COUNT, bArray, (short) (c9Off + PUK_LENGTH), crypto, secp256k1);
puk = new OwnerPIN(PUK_MAX_RETRIES, PUK_LENGTH);
puk.update(bArray, c9Off, PUK_LENGTH);
@ -361,7 +364,7 @@ public class WalletApplet extends Applet {
apduBuffer[off++] = privateKey.isInitialized() ? (byte) 0xFF : (byte) 0x00;
apduBuffer[off++] = TLV_BOOL;
apduBuffer[off++] = 1;
apduBuffer[off++] = SECP256k1.hasECPointMultiplication() ? (byte) 0xFF : (byte) 0x00;
apduBuffer[off++] = secp256k1.hasECPointMultiplication() ? (byte) 0xFF : (byte) 0x00;
return (short) (off - SecureChannel.SC_OUT_OFFSET);
}
@ -513,7 +516,7 @@ public class WalletApplet extends Applet {
short chainOffset = (short)(privOffset + apduBuffer[(short)(privOffset + 1)] + 2);
if (apduBuffer[pubOffset] != TLV_PUB_KEY) {
SECP256k1.assertECPointMultiplicationSupport();
secp256k1.assertECPointMultiplicationSupport();
chainOffset = privOffset;
privOffset = pubOffset;
pubOffset = -1;
@ -547,7 +550,7 @@ public class WalletApplet extends Applet {
pubOffset = (short) (pubOffset + 2);
} else {
pubOffset = 0;
pubLen = SECP256k1.derivePublicKey(masterPrivate, apduBuffer, pubOffset);
pubLen = secp256k1.derivePublicKey(masterPrivate, apduBuffer, pubOffset);
}
masterPublic.setW(apduBuffer, pubOffset, pubLen);
@ -569,13 +572,13 @@ public class WalletApplet extends Applet {
* @param apduBuffer the APDU buffer
*/
private void loadSeed(byte[] apduBuffer) {
SECP256k1.assertECPointMultiplicationSupport();
secp256k1.assertECPointMultiplicationSupport();
if (apduBuffer[ISO7816.OFFSET_LC] != BIP39_SEED_SIZE) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
}
Crypto.bip32MasterFromSeed(apduBuffer, (short) ISO7816.OFFSET_CDATA, BIP39_SEED_SIZE, apduBuffer, (short) ISO7816.OFFSET_CDATA);
crypto.bip32MasterFromSeed(apduBuffer, (short) ISO7816.OFFSET_CDATA, BIP39_SEED_SIZE, apduBuffer, (short) ISO7816.OFFSET_CDATA);
JCSystem.beginTransaction();
isExtended = true;
@ -585,7 +588,7 @@ public class WalletApplet extends Applet {
Util.arrayCopy(apduBuffer, (short) (ISO7816.OFFSET_CDATA + CHAIN_CODE_SIZE), masterChainCode, (short) 0, CHAIN_CODE_SIZE);
Util.arrayCopy(apduBuffer, (short) (ISO7816.OFFSET_CDATA + CHAIN_CODE_SIZE), chainCode, (short) 0, CHAIN_CODE_SIZE);
short pubLen = SECP256k1.derivePublicKey(masterPrivate, apduBuffer, (short) 0);
short pubLen = secp256k1.derivePublicKey(masterPrivate, apduBuffer, (short) 0);
masterPublic.setW(apduBuffer, (short) 0, pubLen);
publicKey.setW(apduBuffer, (short) 0, pubLen);
@ -653,7 +656,7 @@ public class WalletApplet extends Applet {
}
if ((len != 0) && !assistedDerivation) {
SECP256k1.assertECPointMultiplicationSupport();
secp256k1.assertECPointMultiplicationSupport();
}
short chainEnd = (short) (ISO7816.OFFSET_CDATA + len);
@ -669,7 +672,7 @@ public class WalletApplet extends Applet {
copyKeys(privateKey, publicKey, chainCode, parentPrivateKey, parentPublicKey, parentChainCode, apduBuffer, chainEnd);
if (!Crypto.bip32CKDPriv(apduBuffer, i, privateKey, publicKey, chainCode, (short) 0)) {
if (!crypto.bip32CKDPriv(apduBuffer, i, privateKey, publicKey, chainCode, (short) 0)) {
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
}
@ -679,7 +682,7 @@ public class WalletApplet extends Applet {
expectPublicKey = true;
outputPublicX(apdu, apduBuffer);
} else {
short pubLen = SECP256k1.derivePublicKey(privateKey, apduBuffer, chainEnd);
short pubLen = secp256k1.derivePublicKey(privateKey, apduBuffer, chainEnd);
publicKey.setW(apduBuffer, chainEnd, pubLen);
keyPathLen += 4;
parentValid = true;
@ -697,7 +700,7 @@ public class WalletApplet extends Applet {
* @param apduBuffer the APDU buffer.
*/
private void outputPublicX(APDU apdu, byte[] apduBuffer) {
short xLen = SECP256k1.derivePublicX(privateKey, apduBuffer, (short) (SecureChannel.SC_OUT_OFFSET + 4));
short xLen = secp256k1.derivePublicX(privateKey, apduBuffer, (short) (SecureChannel.SC_OUT_OFFSET + 4));
signature.init(privateKey, Signature.MODE_SIGN);
short sigLen = signature.signPreComputedHash(ASSISTED_DERIVATION_HASH, (short) 0, (short) ASSISTED_DERIVATION_HASH.length, apduBuffer, (short) (SecureChannel.SC_OUT_OFFSET + xLen + 4));
@ -774,8 +777,8 @@ public class WalletApplet extends Applet {
}
short entLen = (short) (csLen * 4);
Crypto.random.generateData(apduBuffer, GENERATE_MNEMONIC_TMP_OFF, entLen);
Crypto.sha256.doFinal(apduBuffer, GENERATE_MNEMONIC_TMP_OFF, entLen, apduBuffer, (short)(GENERATE_MNEMONIC_TMP_OFF + entLen));
crypto.random.generateData(apduBuffer, GENERATE_MNEMONIC_TMP_OFF, entLen);
crypto.sha256.doFinal(apduBuffer, GENERATE_MNEMONIC_TMP_OFF, entLen, apduBuffer, (short)(GENERATE_MNEMONIC_TMP_OFF + entLen));
entLen += GENERATE_MNEMONIC_TMP_OFF + 1;
short outOff = SecureChannel.SC_OUT_OFFSET;
@ -875,7 +878,7 @@ public class WalletApplet extends Applet {
ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
}
outLen += Crypto.fixS(apduBuffer, sigOff);
outLen += crypto.fixS(apduBuffer, sigOff);
apduBuffer[(short)(SecureChannel.SC_OUT_OFFSET + 1)] = (byte) 0x81;
apduBuffer[(short)(SecureChannel.SC_OUT_OFFSET + 2)] = (byte) (outLen - 3);