Java Code Examples for javacard.framework.Util#makeShort()
The following examples show how to use
javacard.framework.Util#makeShort() .
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: UtilTLV.java From GidsApplet with GNU General Public License v3.0 | 5 votes |
public static short GetBERTLVDataLen(byte[] buf, short offset, short len) { short size = 0; short sizeforsize = 0; short i = 1; if ((buf[offset] & 0x1F) != 0x1F) { // simplified tag } else { // tag start with all 5 last bits to 1 // skip the tag while (((buf[(short) (offset + i)] & 0x80) != 0) && ((short)(i+offset)) < len) { i++; } // pass the last byte of the tag i+=1; } // check the size if ((buf[(short) (offset + i)] & 0x80) != 0) { // size encoded in many bytes sizeforsize = (short) (buf[(short) (offset + i)] & 0x7F); if (sizeforsize > 2) { // more than two bytes for encoding => not something than we can handle return 0; } else if (sizeforsize == 1) { size = Util.makeShort((byte) 0,buf[(short) (offset + i + 1)]); } else if (sizeforsize == 2) { size = Util.getShort(buf, (short) (offset + i + 1)); } } else { // size encode in one byte size = Util.makeShort((byte) 0,buf[(short) (offset + i)]); } return size; }
Example 2
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 5 votes |
/** * This function creates a PIN with parameters specified by the P1, P2 and DATA * values. P2 specifies the maximum number of consecutive unsuccessful * verifications before the PIN blocks. PIN can be created only if one of the logged identities * allows it. * * ins: 0x40 * p1: PIN number (0x00-0x07) * p2: max attempt number * data: [PIN_size(1b) | PIN | UBLK_size(1b) | UBLK] * return: none */ private short CreatePIN(APDU apdu, byte[] buffer) { // check that PIN[0] has been entered previously if (!pins[0].isValidated()) ISOException.throwIt(SW_UNAUTHORIZED); byte pin_nb = buffer[ISO7816.OFFSET_P1]; byte num_tries = buffer[ISO7816.OFFSET_P2]; if ((pin_nb < 0) || (pin_nb >= MAX_NUM_PINS) || (pins[pin_nb] != null)) ISOException.throwIt(SW_INCORRECT_P1); /* Allow pin lengths > 127 (useful at all ?) */ short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); // At least 1 character for PIN and 1 for unblock code (+ lengths) if (bytesLeft < 4) ISOException.throwIt(SW_INVALID_PARAMETER); byte pin_size = buffer[ISO7816.OFFSET_CDATA]; if (bytesLeft < (short) (1 + pin_size + 1)) ISOException.throwIt(SW_INVALID_PARAMETER); if (!CheckPINPolicy(buffer, (short) (ISO7816.OFFSET_CDATA + 1), pin_size)) ISOException.throwIt(SW_INVALID_PARAMETER); byte ucode_size = buffer[(short) (ISO7816.OFFSET_CDATA + 1 + pin_size)]; if (bytesLeft != (short) (1 + pin_size + 1 + ucode_size)) ISOException.throwIt(SW_INVALID_PARAMETER); if (!CheckPINPolicy(buffer, (short) (ISO7816.OFFSET_CDATA + 1 + pin_size + 1), ucode_size)) ISOException.throwIt(SW_INVALID_PARAMETER); pins[pin_nb] = new OwnerPIN(num_tries, PIN_MAX_SIZE); pins[pin_nb].update(buffer, (short) (ISO7816.OFFSET_CDATA + 1), pin_size); ublk_pins[pin_nb] = new OwnerPIN((byte) 3, PIN_MAX_SIZE); // Recycle variable pin_size pin_size = (byte) (ISO7816.OFFSET_CDATA + 1 + pin_size + 1); ublk_pins[pin_nb].update(buffer, pin_size, ucode_size); return (short)0; }
Example 3
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 5 votes |
/** * This function verifies a PIN number sent by the DATA portion. The length of * this PIN is specified by the value contained in P3. * Multiple consecutive unsuccessful PIN verifications will block the PIN. If a PIN * blocks, then an UnblockPIN command can be issued. * * ins: 0x42 * p1: PIN number (0x00-0x07) * p2: 0x00 * data: [PIN] * return: none (throws an exception in case of wrong PIN) */ private short VerifyPIN(APDU apdu, byte[] buffer) { byte pin_nb = buffer[ISO7816.OFFSET_P1]; if ((pin_nb < 0) || (pin_nb >= MAX_NUM_PINS)) ISOException.throwIt(SW_INCORRECT_P1); OwnerPIN pin = pins[pin_nb]; if (pin == null) ISOException.throwIt(SW_INCORRECT_P1); if (buffer[ISO7816.OFFSET_P2] != 0x00) ISOException.throwIt(SW_INCORRECT_P2); short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); /* * Here I suppose the PIN code is small enough to enter in the buffer * TODO: Verify the assumption and eventually adjust code to support * reading PIN in multiple read()s */ if (!CheckPINPolicy(buffer, ISO7816.OFFSET_CDATA, (byte) bytesLeft)) ISOException.throwIt(SW_INVALID_PARAMETER); byte triesRemaining = pin.getTriesRemaining(); if (triesRemaining == (byte) 0x00) ISOException.throwIt(SW_IDENTITY_BLOCKED); if (!pin.check(buffer, (short) ISO7816.OFFSET_CDATA, (byte) bytesLeft)) { LogoutIdentity(pin_nb); ISOException.throwIt((short)(SW_PIN_FAILED + triesRemaining - 1)); } // Actually register that PIN has been successfully verified. logged_ids |= (short) (0x0001 << pin_nb); return (short)0; }
Example 4
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 5 votes |
/** * This function unblocks a PIN number using the unblock code specified in the * DATA portion. The P3 byte specifies the unblock code length. * * ins: 0x46 * p1: PIN number (0x00-0x07) * p2: 0x00 * data: [PUK] * return: none (throws an exception in case of wrong PUK) */ private short UnblockPIN(APDU apdu, byte[] buffer) { byte pin_nb = buffer[ISO7816.OFFSET_P1]; if ((pin_nb < 0) || (pin_nb >= MAX_NUM_PINS)) ISOException.throwIt(SW_INCORRECT_P1); OwnerPIN pin = pins[pin_nb]; OwnerPIN ublk_pin = ublk_pins[pin_nb]; if (pin == null) ISOException.throwIt(SW_INCORRECT_P1); if (ublk_pin == null) ISOException.throwIt(SW_INTERNAL_ERROR); // If the PIN is not blocked, the call is inconsistent if (pin.getTriesRemaining() != 0) ISOException.throwIt(SW_OPERATION_NOT_ALLOWED); if (buffer[ISO7816.OFFSET_P2] != 0x00) ISOException.throwIt(SW_INCORRECT_P2); short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); /* * Here I suppose the PIN code is small enough to fit into the buffer * TODO: Verify the assumption and eventually adjust code to support * reading PIN in multiple read()s */ if (!CheckPINPolicy(buffer, ISO7816.OFFSET_CDATA, (byte) bytesLeft)) ISOException.throwIt(SW_INVALID_PARAMETER); byte triesRemaining = ublk_pin.getTriesRemaining(); if (triesRemaining == (byte) 0x00) ISOException.throwIt(SW_IDENTITY_BLOCKED); if (!ublk_pin.check(buffer, ISO7816.OFFSET_CDATA, (byte) bytesLeft)) ISOException.throwIt((short)(SW_PIN_FAILED + triesRemaining - 1)); pin.resetAndUnblock(); return (short)0; }
Example 5
Source File: U2FApplet.java From CCU2F with Apache License 2.0 | 5 votes |
private void handleSetAttestationCert(APDU apdu) throws ISOException { byte[] buffer = apdu.getBuffer(); short len = apdu.setIncomingAndReceive(); short dataOffset = apdu.getOffsetCdata(); short copyOffset = Util.makeShort(buffer[ISO7816.OFFSET_P1], buffer[ISO7816.OFFSET_P2]); if ((short)(copyOffset + len) > (short)attestationCertificate.length) { ISOException.throwIt(ISO7816.SW_WRONG_DATA); } Util.arrayCopy(buffer, dataOffset, attestationCertificate, copyOffset, len); if ((short)(copyOffset + len) == (short)attestationCertificate.length) { attestationCertificateSet = true; } }
Example 6
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 5 votes |
/** * This function allows to reset the 2FA key and disable 2FA. * Once activated, 2FA can only be deactivated when the seed is reset and all eckeys cleared. * * ins: 0x78 * p1: 0x00 * p2: 0x00 * data: [hmacsha1_key(20b)] * return: (none) */ private short reset2FAKey(APDU apdu, byte[] buffer){ // check that PIN[0] has been entered previously if (!pins[0].isValidated()) ISOException.throwIt(SW_UNAUTHORIZED); // check length short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); if (bytesLeft < (short)20) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); // reset 2FA can only be done if all private keys are cleared if (!needs_2FA) ISOException.throwIt(SW_2FA_UNINITIALIZED_KEY); if (bip32_seeded) ISOException.throwIt(SW_BIP32_INITIALIZED_SEED); if (eckeys_flag != 0x0000) ISOException.throwIt(SW_ECKEYS_INITIALIZED_KEY); // compute hmac(2FA_ID) and compare with value provided // hmac of 64-bytes msg: (id_2FA(20b) | 44 bytes 0xAA-padding) short offset= ISO7816.OFFSET_CDATA; Util.arrayFillNonAtomic(recvBuffer, (short)0, (short)64, (byte)0xAA); Util.arrayCopyNonAtomic(data2FA, OFFSET_2FA_ID, recvBuffer, (short)0, (short)20); HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, recvBuffer, (short)0, (short)64, recvBuffer, (short)64); if (Util.arrayCompare(buffer, offset, recvBuffer, (short)64, (short)20)!=0) ISOException.throwIt(SW_SIGNATURE_INVALID); // reset flag and data needs_2FA= false; key_2FA.clearKey(); Util.arrayFillNonAtomic(data2FA, (short)0, OFFSET_2FA_SIZE, (byte)0x00); return (short)0; }
Example 7
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 5 votes |
/** * This function allows to set the 2FA key and enable 2FA. * Once activated, 2FA can only be deactivated when the seed is reset. * * ins: 0x79 * p1: 0x00 * p2: 0x00 * data: [hmacsha1_key(20b) | amount_limit(8b)] * return: (none) */ private short set2FAKey(APDU apdu, byte[] buffer){ // check that PIN[0] has been entered previously if (!pins[0].isValidated()) ISOException.throwIt(SW_UNAUTHORIZED); // cannot modify an existing 2FA! if (needs_2FA) ISOException.throwIt(SW_2FA_INITIALIZED_KEY); //check input length short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); if (bytesLeft < (short)(20+8)) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); if (!done_once_2FA){ data2FA= new byte[OFFSET_2FA_SIZE]; randomData = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM); aes128_cbc= Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false); key_2FA= (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false); done_once_2FA= true; } short offset= ISO7816.OFFSET_CDATA; Util.arrayCopyNonAtomic(buffer, offset, data2FA, OFFSET_2FA_HMACKEY, (short)20); offset+=(short)20; Util.arrayCopyNonAtomic(buffer, offset, data2FA, OFFSET_2FA_LIMIT, (short)8); offset+=(short)8; // hmac derivation for id_2FA & key_2FA HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, CST_2FA, (short)0, (short)6, data2FA, OFFSET_2FA_ID); HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, CST_2FA, (short)6, (short)7, recvBuffer, (short)0); key_2FA.setKey(recvBuffer,(short)0); // AES-128: 16-bytes key!! needs_2FA= true; return (short)0; }
Example 8
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 4 votes |
/** * This function resets the Bip32 seed and all derived keys: the master key, chain code, authentikey * and the 32-bit AES key that is used to encrypt/decrypt Bip32 object stored in secure memory. * If 2FA is enabled, then a hmac code must be provided, based on the 4-byte counter-2FA. * * ins: 0x77 * p1: PIN_size * p2: 0x00 * data: [PIN | optional-hmac(20b)] * return: (none) */ private short resetBIP32Seed(APDU apdu, byte[] buffer){ short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); // check provided PIN byte pin_size= buffer[ISO7816.OFFSET_P1]; OwnerPIN pin = pins[(byte)0x00]; if (bytesLeft < pin_size) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); if (!CheckPINPolicy(buffer, ISO7816.OFFSET_CDATA, pin_size)) ISOException.throwIt(SW_INVALID_PARAMETER); byte triesRemaining = pin.getTriesRemaining(); if (triesRemaining == (byte) 0x00) ISOException.throwIt(SW_IDENTITY_BLOCKED); if (!pin.check(buffer, (short) ISO7816.OFFSET_CDATA, (byte) pin_size)) { LogoutIdentity((byte)0x00); ISOException.throwIt((short)(SW_PIN_FAILED + triesRemaining - 1)); } // check if seeded if (!bip32_seeded) ISOException.throwIt(SW_BIP32_UNINITIALIZED_SEED); // check 2FA if required if (needs_2FA){ short offset= Util.makeShort((byte)0, ISO7816.OFFSET_CDATA); offset+=pin_size; bytesLeft-= pin_size; if (bytesLeft < (short)20) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); // compute hmac(counter_2FA) and compare with value provided // hmac of 64-bytes msg: ( authentikey-coordx(32b) | 32bytes 0xFF-padding) Util.arrayFillNonAtomic(recvBuffer, (short)0, (short)64, (byte)0xFF); Util.arrayCopyNonAtomic(authentikey_pubkey, (short)0x01, recvBuffer, (short)0, BIP32_KEY_SIZE); HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, recvBuffer, (short)0, (short)64, recvBuffer, (short)64); if (Util.arrayCompare(buffer, offset, recvBuffer, (short)64, (short)20)!=0) ISOException.throwIt(SW_SIGNATURE_INVALID); } // reset memory cache, bip32 flag and all data! bip32_om.reset(); bip32_seeded= false; bip32_masterkey.clearKey(); bip32_masterchaincode.clearKey(); bip32_encryptkey.clearKey(); bip32_authentikey.clearKey(); Secp256k1.setCommonCurveParameters(bip32_authentikey);// keep public params! Util.arrayFillNonAtomic(authentikey_pubkey, (short)0, (short)(2*BIP32_KEY_SIZE+1), (byte)0x00); LogOutAll(); return (short)0; }
Example 9
Source File: LWNFCForumApplet.java From ledger-javacard with GNU Affero General Public License v3.0 | 4 votes |
@Override public void process(APDU apdu) throws ISOException { if (selectingApplet()) { return; } byte[] buffer = apdu.getBuffer(); if (buffer[ISO7816.OFFSET_CLA] != NFCFORUM_CLA) { ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED); } switch(buffer[ISO7816.OFFSET_INS]) { case INS_SELECT: { apdu.setIncomingAndReceive(); short selectedFile = Util.getShort(buffer, ISO7816.OFFSET_CDATA); switch(selectedFile) { case EF_CONTAINER: scratch[OFFSET_SELECTED_FILE] = SELECTED_FILE_CONTAINER; break; case EF_NDEF: scratch[OFFSET_SELECTED_FILE] = SELECTED_FILE_NDEF; break; default: ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); } } break; case INS_READ: { short offset = Util.makeShort(buffer[ISO7816.OFFSET_P1], buffer[ISO7816.OFFSET_P2]); if (scratch[OFFSET_SELECTED_FILE] == SELECTED_FILE_NONE) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } byte[] fileData = null; switch(scratch[OFFSET_SELECTED_FILE]) { case SELECTED_FILE_CONTAINER: fileData = CONTAINER_DATA; break; case SELECTED_FILE_NDEF: fileData = FILE_DATA; break; } if (offset >= (short)fileData.length) { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } short sizeRead = (short)(buffer[ISO7816.OFFSET_LC] & 0xff); short blockLength = (((short)(offset + sizeRead) > (short)fileData.length) ? (short)(fileData.length - offset) : sizeRead); Util.arrayCopyNonAtomic(fileData, offset, buffer, (short)0, blockLength); apdu.setOutgoingAndSend((short)0, blockLength); } break; } }
Example 10
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 4 votes |
/** * This function allows to decrypt a secure channel message * * ins: 0x82 * * p1: 0x00 (RFU) * p2: 0x00 (RFU) * data: [IV(16b) | data_size(2b) | encrypted_command | mac_size(2b) | mac] * * return: [decrypted command] * */ private short ProcessSecureChannel(APDU apdu, byte[] buffer){ short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); short offset = ISO7816.OFFSET_CDATA; if (!initialized_secure_channel){ ISOException.throwIt(SW_SECURE_CHANNEL_UNINITIALIZED); } // check hmac if (bytesLeft<18) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); short sizein = Util.getShort(buffer, (short) (offset+SIZE_SC_IV)); if (bytesLeft<(short)(SIZE_SC_IV+2+sizein+2)) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); short sizemac= Util.getShort(buffer, (short) (offset+SIZE_SC_IV+2+sizein)); if (sizemac != (short)20) ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_MAC); if (bytesLeft<(short)(SIZE_SC_IV+2+sizein+2+sizemac)) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); HmacSha160.computeHmacSha160(sc_buffer, OFFSET_SC_MACKEY, SIZE_SC_MACKEY, buffer, offset, (short)(SIZE_SC_IV+2+sizein), recvBuffer, (short)0); if ( Util.arrayCompare(recvBuffer, (short)0, buffer, (short)(offset+SIZE_SC_IV+2+sizein+2), (short)20) != (byte)0 ) ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_MAC); // process IV // IV received from client should be odd and strictly greater than locally saved IV // IV should be random (the 12 first bytes), never reused (the last 4 bytes counter) and different for send and receive if ((buffer[(short)(offset+SIZE_SC_IV-(short)1)] & (byte)0x01)==0x00)// should be odd ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_IV); if ( !Biginteger.lessThan(sc_buffer, OFFSET_SC_IV_COUNTER, buffer, (short)(offset+SIZE_SC_IV_RANDOM), SIZE_SC_IV_COUNTER ) ) //and greater than local IV ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_IV); // update local IV Util.arrayCopy(buffer, (short)(offset+SIZE_SC_IV_RANDOM), sc_buffer, OFFSET_SC_IV_COUNTER, SIZE_SC_IV_COUNTER); Biginteger.add1_carry(sc_buffer, OFFSET_SC_IV_COUNTER, SIZE_SC_IV_COUNTER); randomData.generateData(sc_buffer, OFFSET_SC_IV_RANDOM, SIZE_SC_IV_RANDOM); sc_aes128_cbc.init(sc_sessionkey, Cipher.MODE_DECRYPT, buffer, offset, SIZE_SC_IV); offset+=SIZE_SC_IV; bytesLeft-=SIZE_SC_IV; //decrypt command offset+=2; bytesLeft-=2; if (bytesLeft<sizein) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); short sizeout=sc_aes128_cbc.doFinal(buffer, offset, sizein, buffer, (short) (0)); return sizeout; }
Example 11
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 4 votes |
/** * This function allows to initiate a Secure Channel * * ins: 0x81 * p1: 0x00 * p2: 0x00 * data: [client-pubkey(65b)] * return: [coordx_size(2b) | authentikey-coordx | sig_size(2b) | self-sig | sig2_size(optional) | authentikey-sig(optional)] */ private short InitiateSecureChannel(APDU apdu, byte[] buffer){ // get client pubkey short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); if (bytesLeft < (short)65) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); if (buffer[ISO7816.OFFSET_CDATA] != (byte)0x04) ISOException.throwIt(SW_INVALID_PARAMETER); // generate a new ephemeral key sc_ephemeralkey.clearKey(); Secp256k1.setCommonCurveParameters(sc_ephemeralkey);// keep public params! randomData.generateData(recvBuffer, (short)0, BIP32_KEY_SIZE); sc_ephemeralkey.setS(recvBuffer, (short)0, BIP32_KEY_SIZE); //random value first // compute the shared secret... keyAgreement.init(sc_ephemeralkey); short coordx_size= (short)32; keyAgreement.generateSecret(buffer, ISO7816.OFFSET_CDATA, (short) 65, recvBuffer, (short)0); //pubkey in uncompressed form // derive sc_sessionkey & sc_mackey HmacSha160.computeHmacSha160(recvBuffer, (short)1, (short)32, CST_SC, (short)6, (short)6, recvBuffer, (short)33); Util.arrayCopyNonAtomic(recvBuffer, (short)33, sc_buffer, OFFSET_SC_MACKEY, SIZE_SC_MACKEY); HmacSha160.computeHmacSha160(recvBuffer, (short)1, (short)32, CST_SC, (short)0, (short)6, recvBuffer, (short)33); sc_sessionkey.setKey(recvBuffer,(short)33); // AES-128: 16-bytes key!! // //alternatively: derive session_key (sha256 of coordx) // sha256.reset(); // sha256.doFinal(recvBuffer, (short)1, (short)32, recvBuffer, (short) 0); // sc_sessionkey.setKey(recvBuffer,(short)0); // AES-128: 16-bytes key!! // //derive mac_key // sha256.reset(); // sha256.doFinal(recvBuffer, (short)0, (short)32, sc_mackey, (short) 0); //reset IV counter Util.arrayFillNonAtomic(sc_buffer, OFFSET_SC_IV, SIZE_SC_IV, (byte) 0); // self signed ephemeral pubkey keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, buffer, (short)1); //pubkey in uncompressed form Util.setShort(buffer, (short)0, coordx_size); sigECDSA.init(sc_ephemeralkey, Signature.MODE_SIGN); short sign_size= sigECDSA.sign(buffer, (short)0, (short)(coordx_size+2), buffer, (short)(coordx_size+4)); Util.setShort(buffer, (short)(coordx_size+2), sign_size); // hash signed by authentikey if seed is initialized short offset= (short)(2+coordx_size+2+sign_size); if (bip32_seeded){ sigECDSA.init(bip32_authentikey, Signature.MODE_SIGN); short sign2_size= sigECDSA.sign(buffer, (short)0, offset, buffer, (short)(offset+2)); Util.setShort(buffer, offset, sign2_size); offset+=(short)(2+sign2_size); }else{ Util.setShort(buffer, offset, (short)0); offset+=(short)2; } initialized_secure_channel= true; // return x-coordinate of public key+signature // the client can recover full public-key from the signature or // by guessing the compression value () and verifying the signature... // buffer= [coordx_size(2) | coordx | sigsize(2) | sig | sig2_size(optional) | sig2(optional)] return offset; }
Example 12
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 4 votes |
/** * This function encrypts/decrypt a given message with a 16bytes secret key derived from the 2FA key. * It also returns an id derived from the 2FA key. * This is used to privately exchange tx data between the hw wallet and the 2FA device. * * Algorithms: * id_2FA is hmac-sha1(secret_2FA, "id_2FA"), * key_2FA is hmac-sha1(secret_2FA, "key_2FA"), * message encrypted using AES * * ins: 0x76 * p1: 0x00 for encryption, 0x01 for decryption * p2: Init-Update-Finalize * data(init): IF_ENCRYPT: none ELSE: [IV(16b)] * data(update/finalize): [chunk_size(2b) | chunk_data] * * return(init): IF_ENCRYPT:[IV(16b) | id_2FA(20b)] ELSE: none * return(update/finalize): [chunk_size(2b) | chunk_data] * * */ private short CryptTransaction2FA(APDU apdu, byte[] buffer){ // check that PIN[0] has been entered previously if (!pins[0].isValidated()) ISOException.throwIt(SW_UNAUTHORIZED); // check that 2FA is enabled if (!needs_2FA) ISOException.throwIt(SW_2FA_UNINITIALIZED_KEY); byte ciph_dir = buffer[ISO7816.OFFSET_P1]; byte ciph_op = buffer[ISO7816.OFFSET_P2]; short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); short dataOffset = ISO7816.OFFSET_CDATA; short IVlength=(short)16; switch(ciph_op){ case OP_INIT: if (ciph_dir!=Cipher.MODE_ENCRYPT && ciph_dir!=Cipher.MODE_DECRYPT ) ISOException.throwIt(SW_INVALID_PARAMETER); if (ciph_dir==Cipher.MODE_ENCRYPT){ randomData.generateData(buffer,(short)0, IVlength); aes128_cbc.init(key_2FA, Cipher.MODE_ENCRYPT, buffer, (short)0, IVlength); Util.arrayCopyNonAtomic(data2FA, OFFSET_2FA_ID, buffer, (short)IVlength, (short)20); return (short)(IVlength + 20); } if (ciph_dir==Cipher.MODE_DECRYPT){ aes128_cbc.init(key_2FA, Cipher.MODE_DECRYPT, buffer, dataOffset, IVlength); return (short)0; } break; case OP_PROCESS: case OP_FINALIZE: if (bytesLeft < 2) ISOException.throwIt(SW_INVALID_PARAMETER); short size = Util.getShort(buffer, dataOffset); if (bytesLeft < (short) (2 + size)) ISOException.throwIt(SW_INVALID_PARAMETER); short sizeout=0; if (ciph_op == OP_PROCESS){ sizeout=aes128_cbc.update(buffer, (short) (dataOffset + 2), size, buffer, (short) 2); } else {// ciph_op == OP_FINALIZE sizeout=aes128_cbc.doFinal(buffer, (short) (dataOffset + 2), size, buffer, (short) 2); } // Also copies the Short size information Util.setShort(buffer,(short)0, sizeout); return (short) (sizeout + 2); default: ISOException.throwIt(SW_INCORRECT_P2); } return (short)0; }
Example 13
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 4 votes |
/** * This function signs a given transaction hash with a std or the last extended key * If 2FA is enabled, a HMAC must be provided as an additional security layer. * * ins: 0x7A * p1: key number or 0xFF for the last derived Bip32 extended key * p2: 0x00 * data: [hash(32b) | option: 2FA-flag(2b)|hmac(20b)] * * return: [sig ] * */ private short SignTransactionHash(APDU apdu, byte[] buffer){ // check that PIN[0] has been entered previously if (!pins[0].isValidated()) ISOException.throwIt(SW_UNAUTHORIZED); byte key_nb = buffer[ISO7816.OFFSET_P1]; if ( (key_nb!=(byte)0xFF) && ((key_nb < 0) || (key_nb >= MAX_NUM_KEYS)) ) ISOException.throwIt(SW_INCORRECT_P1); short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); if (bytesLeft<MessageDigest.LENGTH_SHA_256) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); // check whether the seed is initialized if (key_nb==(byte)0xFF && !bip32_seeded) ISOException.throwIt(SW_BIP32_UNINITIALIZED_SEED); // check 2FA if required if(needs_2FA){ // check data length if (bytesLeft<MessageDigest.LENGTH_SHA_256+MessageDigest.LENGTH_SHA+(short)2) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); // check flag for 2fa_hmac_chalresp short hmac_flags= Util.getShort(buffer, (short)(ISO7816.OFFSET_CDATA+32)); if (hmac_flags!=HMAC_CHALRESP_2FA) ISOException.throwIt(SW_INCORRECT_ALG); // hmac of 64-bytes msg: ( 32bytes tx_hash | 32bytes 0xCC-padding) Util.arrayCopyNonAtomic(buffer, (short)ISO7816.OFFSET_CDATA, recvBuffer, (short)0, (short)32); Util.arrayFillNonAtomic(recvBuffer, (short)32, (short)32, (byte)0xCC); HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, recvBuffer, (short)0, (short)64, recvBuffer, (short)64); if (Util.arrayCompare(buffer, (short)(ISO7816.OFFSET_CDATA+32+2), recvBuffer, (short)64, (short)20)!=0) ISOException.throwIt(SW_SIGNATURE_INVALID); } // hash+sign singlehash if (key_nb==(byte)0xFF) sigECDSA.init(bip32_extendedkey, Signature.MODE_SIGN); else{ Key key= eckeys[key_nb]; // check type and size if ((key == null) || !key.isInitialized()) ISOException.throwIt(SW_INCORRECT_P1); if (key.getType() != KeyBuilder.TYPE_EC_FP_PRIVATE) ISOException.throwIt(SW_INCORRECT_ALG); if (key.getSize()!= LENGTH_EC_FP_256) ISOException.throwIt(SW_INCORRECT_ALG); sigECDSA.init(key, Signature.MODE_SIGN); } short sign_size= sigECDSA.signPreComputedHash(buffer, ISO7816.OFFSET_CDATA, MessageDigest.LENGTH_SHA_256, buffer, (short)0); return sign_size; }
Example 14
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 4 votes |
/** * This function signs the current hash transaction with a std or the last extended key * The hash provided in the APDU is compared to the version stored inside the chip. * Depending of the total amount in the transaction and the predefined limit, * a HMAC must be provided as an additional security layer. * * ins: 0x6F * p1: key number or 0xFF for the last derived Bip32 extended key * p2: 0x00 * data: [hash(32b) | option: 2FA-flag(2b)|hmac(20b)] * * return: [sig ] * */ private short SignTransaction(APDU apdu, byte[] buffer){ // check that PIN[0] has been entered previously if (!pins[0].isValidated()) ISOException.throwIt(SW_UNAUTHORIZED); byte key_nb = buffer[ISO7816.OFFSET_P1]; if ( (key_nb!=(byte)0xFF) && ((key_nb < 0) || (key_nb >= MAX_NUM_KEYS)) ) ISOException.throwIt(SW_INCORRECT_P1); short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); if (bytesLeft<MessageDigest.LENGTH_SHA_256) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); // check whether the seed is initialized if (key_nb==(byte)0xFF && !bip32_seeded) ISOException.throwIt(SW_BIP32_UNINITIALIZED_SEED); // check doublehash value in buffer with cached singlehash value sha256.reset(); sha256.doFinal(transactionData, OFFSET_TRANSACTION_HASH, MessageDigest.LENGTH_SHA_256, recvBuffer, (short)0); if ((byte)0 != Util.arrayCompare(buffer, ISO7816.OFFSET_CDATA, recvBuffer, (short)0, MessageDigest.LENGTH_SHA_256)) ISOException.throwIt(SW_INCORRECT_TXHASH); // check challenge-response answer if necessary if(needs_2FA){ if( Biginteger.lessThan(data2FA, OFFSET_2FA_LIMIT, transactionData, OFFSET_TRANSACTION_AMOUNT, (short)8)){ if (bytesLeft<MessageDigest.LENGTH_SHA_256+MessageDigest.LENGTH_SHA+(short)2) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); // check flag for 2fa_hmac_chalresp short hmac_flags= Util.getShort(buffer, (short)(ISO7816.OFFSET_CDATA+32)); if (hmac_flags!=HMAC_CHALRESP_2FA) ISOException.throwIt(SW_INCORRECT_ALG); // hmac of 64-bytes msg: (doublesha256(raw_tx) | 32bytes zero-padding) Util.arrayFillNonAtomic(recvBuffer, (short)32, (short)32, (byte)0x00); HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, recvBuffer, (short)0, (short)64, recvBuffer, (short)64); if (Util.arrayCompare(buffer, (short)(ISO7816.OFFSET_CDATA+32+2), recvBuffer, (short)64, (short)20)!=0) ISOException.throwIt(SW_SIGNATURE_INVALID); // reset total amount Util.arrayFillNonAtomic(transactionData, OFFSET_TRANSACTION_TOTAL, (short)8, (byte)0x00); } else{ //update total amount Util.arrayCopyNonAtomic(transactionData, OFFSET_TRANSACTION_AMOUNT, transactionData, OFFSET_TRANSACTION_TOTAL, (short)8); } } // hash+sign singlehash if (key_nb==(byte)0xFF) sigECDSA.init(bip32_extendedkey, Signature.MODE_SIGN); else{ Key key= eckeys[key_nb]; // check type and size if ((key == null) || !key.isInitialized()) ISOException.throwIt(SW_INCORRECT_P1); if (key.getType() != KeyBuilder.TYPE_EC_FP_PRIVATE) ISOException.throwIt(SW_INCORRECT_ALG); if (key.getSize()!= LENGTH_EC_FP_256) ISOException.throwIt(SW_INCORRECT_ALG); sigECDSA.init(key, Signature.MODE_SIGN); } short sign_size= sigECDSA.sign(transactionData, OFFSET_TRANSACTION_HASH, (short)32, buffer, (short)0); return sign_size; }
Example 15
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 4 votes |
/** * This function imports a Bip32 seed to the applet and derives the master key and chain code. * It also derives a second ECC that uniquely authenticates the HDwallet: the authentikey. * Lastly, it derives a 32-bit AES key that is used to encrypt/decrypt Bip32 object stored in secure memory * If the seed already exists, it is reset if the logged identities allow it. * * The function returns the x-coordinate of the authentikey, self-signed. * The authentikey full public key can be recovered from the signature. * * ins: 0x6C * p1: seed_size(1b) * p2: 0x00 * data: [seed_data (seed_size)] * return: [coordx_size(2b) | coordx | sig_size(2b) | sig] */ private short importBIP32Seed(APDU apdu, byte[] buffer){ // check that PIN[0] has been entered previously if (!pins[0].isValidated()) ISOException.throwIt(SW_UNAUTHORIZED); if (buffer[ISO7816.OFFSET_P2] != (byte) 0x00) ISOException.throwIt(SW_INCORRECT_P2); // if already seeded, must call resetBIP32Seed first! if (bip32_seeded) ISOException.throwIt(SW_BIP32_INITIALIZED_SEED); short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); // get seed bytesize (max 64 bytes) byte bip32_seedsize = buffer[ISO7816.OFFSET_P1]; if (bip32_seedsize <0 || bip32_seedsize>64) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); short offset= (short)ISO7816.OFFSET_CDATA; // derive master key! HmacSha512.computeHmacSha512(BITCOIN_SEED, (short)0, (short)BITCOIN_SEED.length, buffer, offset, (short)bip32_seedsize, recvBuffer, (short)0); bip32_masterkey.setKey(recvBuffer, (short)0); // data must be exactly 32 bytes long bip32_masterchaincode.setKey(recvBuffer, (short)32); // data must be exactly 32 bytes long // derive 2 more keys from seed: // - AES encryption key for secure storage of extended keys in object // - ECC key for authentication of sensitive data returned by the applet (hash, pubkeys) HmacSha512.computeHmacSha512(BITCOIN_SEED2, (short)0, (short)BITCOIN_SEED2.length, buffer, offset, (short)bip32_seedsize, recvBuffer, (short)64); bip32_authentikey.setS(recvBuffer, (short)64, BIP32_KEY_SIZE); bip32_encryptkey.setKey(recvBuffer, (short)96); // AES-128: 16-bytes key!! // bip32 is now seeded bip32_seeded= true; // clear recvBuffer Util.arrayFillNonAtomic(recvBuffer, (short)0, (short)128, (byte)0); // compute the partial authentikey public key... keyAgreement.init(bip32_authentikey); short coordx_size= (short)32; keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, authentikey_pubkey, (short)0); //pubkey in uncompressed form Util.setShort(buffer, (short)0, coordx_size); Util.arrayCopyNonAtomic(authentikey_pubkey, (short)1, buffer, (short)2, coordx_size); // self signed public key sigECDSA.init(bip32_authentikey, Signature.MODE_SIGN); short sign_size= sigECDSA.sign(buffer, (short)0, (short)(coordx_size+2), buffer, (short)(coordx_size+4)); Util.setShort(buffer, (short)(2+coordx_size), sign_size); // return x-coordinate of public key+signature // the client can recover full public-key from the signature or // by guessing the compression value () and verifying the signature... // buffer= [coordx_size(2) | coordx | sigsize(2) | sig] return (short)(2+coordx_size+2+sign_size); }
Example 16
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 4 votes |
/** * This function changes a PIN code. The DATA portion contains both the old and * the new PIN codes. * * ins: 0x44 * p1: PIN number (0x00-0x07) * p2: 0x00 * data: [PIN_size(1b) | old_PIN | PIN_size(1b) | new_PIN ] * return: none (throws an exception in case of wrong PIN) */ private short ChangePIN(APDU apdu, byte[] buffer) { /* * Here I suppose the PIN code is small enough that 2 of them enter in * the buffer TODO: Verify the assumption and eventually adjust code to * support reading PINs in multiple read()s */ byte pin_nb = buffer[ISO7816.OFFSET_P1]; if ((pin_nb < 0) || (pin_nb >= MAX_NUM_PINS)) ISOException.throwIt(SW_INCORRECT_P1); OwnerPIN pin = pins[pin_nb]; if (pin == null) ISOException.throwIt(SW_INCORRECT_P1); if (buffer[ISO7816.OFFSET_P2] != (byte) 0x00) ISOException.throwIt(SW_INCORRECT_P2); short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); // At least 1 character for each PIN code if (bytesLeft < 4) ISOException.throwIt(SW_INVALID_PARAMETER); byte pin_size = buffer[ISO7816.OFFSET_CDATA]; if (bytesLeft < (short) (1 + pin_size + 1)) ISOException.throwIt(SW_INVALID_PARAMETER); if (!CheckPINPolicy(buffer, (short) (ISO7816.OFFSET_CDATA + 1), pin_size)) ISOException.throwIt(SW_INVALID_PARAMETER); byte new_pin_size = buffer[(short) (ISO7816.OFFSET_CDATA + 1 + pin_size)]; if (bytesLeft < (short) (1 + pin_size + 1 + new_pin_size)) ISOException.throwIt(SW_INVALID_PARAMETER); if (!CheckPINPolicy(buffer, (short) (ISO7816.OFFSET_CDATA + 1 + pin_size + 1), new_pin_size)) ISOException.throwIt(SW_INVALID_PARAMETER); byte triesRemaining = pin.getTriesRemaining(); if (triesRemaining == (byte) 0x00) ISOException.throwIt(SW_IDENTITY_BLOCKED); if (!pin.check(buffer, (short) (ISO7816.OFFSET_CDATA + 1), pin_size)) { LogoutIdentity(pin_nb); ISOException.throwIt((short)(SW_PIN_FAILED + triesRemaining - 1)); } pin.update(buffer, (short) (ISO7816.OFFSET_CDATA + 1 + pin_size + 1), new_pin_size); // JC specifies this resets the validated flag. So we do. logged_ids &= (short) ((short) 0xFFFF ^ (0x01 << pin_nb)); return (short)0; }
Example 17
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 4 votes |
/** * This function allows to reset a private ECkey stored in the card. * If 2FA is enabled, a hmac code must be provided to reset the key. * * ins: 0x33 * p1: private key number (0x00-0x0F) * p2: 0x00 * data: [ (option)HMAC-2FA(20b)] * return: none */ private short ResetKey(APDU apdu, byte[] buffer) { // check that PIN[0] has been entered previously if (!pins[0].isValidated()) ISOException.throwIt(SW_UNAUTHORIZED); if (buffer[ISO7816.OFFSET_P2] != (byte) 0x00) ISOException.throwIt(SW_INCORRECT_P2); byte key_nb = buffer[ISO7816.OFFSET_P1]; if ((key_nb < 0) || (key_nb >= MAX_NUM_KEYS)) ISOException.throwIt(SW_INCORRECT_P1); Key key = eckeys[key_nb]; // check type and size if ((key == null) || !key.isInitialized()) ISOException.throwIt(SW_INCORRECT_P1); // check 2FA if required if (needs_2FA){ short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); if (bytesLeft < (short)20) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); // compute the corresponding partial public key... keyAgreement.init((ECPrivateKey)key); keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, tmpBuffer, (short)0); //pubkey in uncompressed form Util.arrayCopy(tmpBuffer, (short)1, recvBuffer, (short)0, (short)32); // hmac of 64-bytes msg: (pubkey-x | 32bytes (0x20^key_nb)-padding) Util.arrayFillNonAtomic(recvBuffer, (short)32, (short)32, (byte) (0x20^key_nb)); HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, recvBuffer, (short)0, (short)64, recvBuffer, (short)64); if (Util.arrayCompare(buffer, ISO7816.OFFSET_CDATA, recvBuffer, (short)64, (short)20)!=0) ISOException.throwIt(SW_SIGNATURE_INVALID); } // clear key & reset flag key.clearKey(); eckeys_flag &= (short) ~(0x0001 << key_nb);// reset corresponding bit flag; return (short)0; }
Example 18
Source File: UtilTLV.java From GidsApplet with GNU General Public License v3.0 | 4 votes |
public static short CheckBERTLV(byte[] buf, short offset, short len) { short size = 0; short sizeforsize = 0; short i = 1; short totalsize = 0; if ((buf[offset] & 0x1F) != 0x1F) { // simplified tag } else { // tag start with all 5 last bits to 1 // skip the tag while (((buf[(short) (offset + i)] & 0x80) != 0) && i < len) { i++; } // pass the last byte of the tag i+=1; } if ((short) (i+1) >len) { return 0; } // check the size if ((buf[(short) (offset + i)] & 0x80) != 0) { // size encoded in many bytes sizeforsize = (short) (buf[(short) (offset + i)] & 0x7F); if ((short) (i+1+sizeforsize) >len) { return 0; } if (sizeforsize > (short) 2) { // more than two bytes for encoding => not something than we can handle return 0; } else if (sizeforsize == (short) 1) { if ((short) (offset + i + 1 + sizeforsize) > len) { return 0; } size = Util.makeShort((byte) 0,buf[(short) (offset + i + 1)]); } else if (sizeforsize == 2) { totalsize = (short) (i + 1 + sizeforsize + size); if ((short) (offset + i + 1 + sizeforsize) > len) { return (short) 0; } size = Util.getShort(buf, (short) (offset + i + 1)); } } else { // size encode in one byte size = Util.makeShort((byte) 0,buf[(short) (offset + i)]); } totalsize = (short) (i + 1 + sizeforsize + size); if (totalsize < (short) 240 && (short) (offset + totalsize) > len) { return (short) 0; } return totalsize; }