Java Code Examples for javacard.framework.ISO7816#OFFSET_P2
The following examples show how to use
javacard.framework.ISO7816#OFFSET_P2 .
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: OCUnitTests.java From JCMathLib with MIT License | 6 votes |
void test_BN_EXP(APDU apdu, short dataLen) { byte[] apdubuf = apdu.getBuffer(); short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF); short p2 = (short) (apdubuf[ISO7816.OFFSET_P2] & 0x00FF); PM.check(PM.TRAP_BN_EXP_1); Bignat base = m_testBN1; base.set_size(p1); PM.check(PM.TRAP_BN_EXP_2); Bignat exp = m_testBN2; exp.set_size((short) (dataLen - p1)); PM.check(PM.TRAP_BN_EXP_3); Bignat res = m_testBN3; res.set_size((short) (m_ecc.MAX_BIGNAT_SIZE / 2)); PM.check(PM.TRAP_BN_EXP_4); base.from_byte_array(p1, (short) 0, apdubuf, ISO7816.OFFSET_CDATA); exp.from_byte_array((short) (dataLen - p1), (short) 0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1)); PM.check(PM.TRAP_BN_EXP_5); res.exponentiation(base, exp); PM.check(PM.TRAP_BN_EXP_6); short len = res.copy_to_buffer(apdubuf, (short) 0); apdu.setOutgoingAndSend((short) 0, len); }
Example 2
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 6 votes |
/** * This function returns a 2 byte bit mask of the available PINs that are currently in * use. Each set bit corresponds to an active PIN. * * ins: 0x48 * p1: 0x00 * p2: 0x00 * data: none * return: [RFU(1b) | PIN_mask(1b)] */ private short ListPINs(APDU apdu, byte[] buffer) { // check that PIN[0] has been entered previously if (!pins[0].isValidated()) ISOException.throwIt(SW_UNAUTHORIZED); // Checking P1 & P2 if (buffer[ISO7816.OFFSET_P1] != (byte) 0x00) ISOException.throwIt(SW_INCORRECT_P1); if (buffer[ISO7816.OFFSET_P2] != (byte) 0x00) ISOException.throwIt(SW_INCORRECT_P2); byte expectedBytes = (byte) (buffer[ISO7816.OFFSET_LC]); if (expectedBytes != (short) 2) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); // Build the PIN bit mask short mask = (short) 0x00; short b; for (b = (short) 0; b < MAX_NUM_PINS; b++) if (pins[b] != null) mask |= (short) (((short) 0x01) << b); // Fill the buffer Util.setShort(buffer, (short) 0, mask); // Send response return (short)2; }
Example 3
Source File: OCUnitTests.java From JCMathLib with MIT License | 6 votes |
void test_BN_POW2_MOD(APDU apdu, short dataLen) { byte[] apdubuf = apdu.getBuffer(); short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF); short p2 = (short) (apdubuf[ISO7816.OFFSET_P2] & 0x00FF); PM.check(PM.TRAP_BN_POW2_MOD_1); Bignat num1 = m_testBN1; num1.set_size(p1); Bignat mod = m_testBN3; mod.set_size((short) (dataLen - p1)); num1.from_byte_array(p1, (short) 0, apdubuf, ISO7816.OFFSET_CDATA); mod.from_byte_array((short) (dataLen - p1), (short) 0, apdubuf, (short) (ISO7816.OFFSET_CDATA + p1)); PM.check(PM.TRAP_BN_POW2_MOD_2); //num1.pow2Mod_RSATrick(mod); num1.mod_exp2(mod); PM.check(PM.TRAP_BN_POW2_MOD_3); short len = num1.copy_to_buffer(apdubuf, (short) 0); apdu.setOutgoingAndSend((short) 0, len); }
Example 4
Source File: OCUnitTests.java From JCMathLib with MIT License | 6 votes |
void test_EC_SETCURVE_G(APDU apdu, short dataLen) { byte[] apdubuf = apdu.getBuffer(); Util.arrayCopyNonAtomic(apdubuf, ISO7816.OFFSET_CDATA, m_customG, (short) 0, dataLen); PM.check(PM.TRAP_EC_SETCURVE_1); if (apdubuf[ISO7816.OFFSET_P2] == 1) { // If required, complete new custom curve and point is allocated m_testCurveCustom = new ECCurve(false, SecP256r1.p, SecP256r1.a, SecP256r1.b, m_customG, SecP256r1.r); m_testPointCustom = new ECPoint(m_testCurveCustom, m_ecc.ech); PM.check(PM.TRAP_EC_SETCURVE_2); // Release unused previous objects if (!bIsSimulator) { JCSystem.requestObjectDeletion(); } } else { // Otherwise, only G is set and relevant objects are updated m_testCurveCustom.setG(apdubuf, (short) ISO7816.OFFSET_CDATA, m_testCurveCustom.POINT_SIZE); m_testPointCustom.updatePointObjects(); // After changing curve parameters, internal objects needs to be actualized } }
Example 5
Source File: GidsApplet.java From GidsApplet with GNU General Public License v3.0 | 5 votes |
/** * \brief Process the PERFORM SECURITY OPERATION apdu (INS=2A). * * This operation is used for cryptographic operations * (Computation of digital signatures, decrypting.). * * \param apdu The PERFORM SECURITY OPERATION apdu. * * \throw ISOException SW_SECURITY_STATUS_NOT_SATISFIED, SW_INCORRECT_P1P2 and * the ones from computeDigitalSignature() and decipher(). */ private void processPerformSecurityOperation(APDU apdu) throws ISOException { byte[] buf = apdu.getBuffer(); byte p1 = buf[ISO7816.OFFSET_P1]; byte p2 = buf[ISO7816.OFFSET_P2]; if(p1 == (byte) 0x9E && p2 == (byte) 0x9A) { computeDigitalSignature(apdu); } else if(p1 == (byte) 0x80 && p2 == (byte) 0x86) { decipher(apdu); } else { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } }
Example 6
Source File: Gpg.java From OpenPGP-Card with GNU General Public License v3.0 | 5 votes |
/** * CHANGE REFERENCE DATA APDU implementation. */ private void changeReferenceData(APDU apdu) { byte buffer[] = apdu.getBuffer(); if (buffer[ISO7816.OFFSET_P1] != (byte) 0) { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } byte pinOffset = PIN_INDEX_PW1; byte minLength = MIN_PIN1_LENGTH; byte type = buffer[ISO7816.OFFSET_P2]; if (type == (byte) 0x83) { pinOffset = PIN_INDEX_PW3; minLength = MIN_PIN3_LENGTH; } else if (type != (byte) 0x81) { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } byte currentLength = pinLength[pinOffset]; short length = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF); if (apdu.setIncomingAndReceive() != length || length > currentLength + MAX_PIN_LENGTH || length < currentLength + minLength) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (pins[pinOffset].getTriesRemaining() == 0) { ISOException.throwIt(SW_PIN_BLOCKED); } if (!pins[pinOffset].check(buffer, ISO7816.OFFSET_CDATA, currentLength)) { pinSubmitted[0] = false; ISOException.throwIt((short) (SW_PIN_FAILED_00 + pins[pinOffset].getTriesRemaining())); } updatePIN(pinOffset, buffer, (short) (ISO7816.OFFSET_CDATA + currentLength), (byte) (length - currentLength)); }
Example 7
Source File: NdefApplet.java From openjavacard-ndef with GNU General Public License v3.0 | 5 votes |
/** * Process a SELECT command * * This handles only the one case mandated by the NDEF * specification: SELECT FIRST-OR-ONLY BY-FILE-ID. * * The file ID is specified in the APDU contents. It * must be exactly two bytes long and also valid. * * @param apdu to process * @throws ISOException on error */ private void processSelect(APDU apdu) throws ISOException { byte[] buffer = apdu.getBuffer(); byte p1 = buffer[ISO7816.OFFSET_P1]; byte p2 = buffer[ISO7816.OFFSET_P2]; // we only support what the NDEF spec prescribes if(p1 != SELECT_P1_BY_FILEID || p2 != SELECT_P2_FIRST_OR_ONLY) { ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); } // receive data short lc = apdu.setIncomingAndReceive(); // check length, must be for a file ID if(lc != 2) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } // retrieve the file ID short fileId = Util.getShort(buffer, ISO7816.OFFSET_CDATA); // perform selection if the ID is valid if(fileId == FILEID_NDEF_CAPABILITIES || fileId == FILEID_NDEF_DATA) { vars[VAR_SELECTED_FILE] = fileId; } else { ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); } }
Example 8
Source File: NdefApplet.java From openjavacard-ndef with GNU General Public License v3.0 | 5 votes |
/** * Process a SELECT command * * This handles only the one case mandated by the NDEF * specification: SELECT FIRST-OR-ONLY BY-FILE-ID. * * The file ID is specified in the APDU contents. It * must be exactly two bytes long and also valid. * * @param apdu to process * @throws ISOException on error */ private void processSelect(APDU apdu) throws ISOException { byte[] buffer = apdu.getBuffer(); byte p1 = buffer[ISO7816.OFFSET_P1]; byte p2 = buffer[ISO7816.OFFSET_P2]; // we only support what the NDEF spec prescribes if(p1 != SELECT_P1_BY_FILEID || p2 != SELECT_P2_FIRST_OR_ONLY) { ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); } // receive data short lc = apdu.setIncomingAndReceive(); // check length, must be for a file ID if(lc != 2) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } // retrieve the file ID short fileId = Util.getShort(buffer, ISO7816.OFFSET_CDATA); // perform selection if the ID is valid if(fileId == FILEID_NDEF_CAPABILITIES || fileId == FILEID_NDEF_DATA) { vars[VAR_SELECTED_FILE] = fileId; } else { ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); } }
Example 9
Source File: NdefApplet.java From openjavacard-ndef with GNU General Public License v3.0 | 5 votes |
/** * Process a SELECT command * * This handles only the one case mandated by the NDEF * specification: SELECT FIRST-OR-ONLY BY-FILE-ID. * * The file ID is specified in the APDU contents. It * must be exactly two bytes long and also valid. * * @param apdu to process * @throws ISOException on error */ private void processSelect(APDU apdu) throws ISOException { byte[] buffer = apdu.getBuffer(); byte p1 = buffer[ISO7816.OFFSET_P1]; byte p2 = buffer[ISO7816.OFFSET_P2]; // we only support what the NDEF spec prescribes if(p1 != SELECT_P1_BY_FILEID || p2 != SELECT_P2_FIRST_OR_ONLY) { ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); } // receive data short lc = apdu.setIncomingAndReceive(); // check length, must be for a file ID if(lc != 2) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } // retrieve the file ID short fileId = Util.getShort(buffer, ISO7816.OFFSET_CDATA); // perform selection if the ID is valid if(fileId == FILEID_NDEF_CAPABILITIES || fileId == FILEID_NDEF_DATA) { vars[VAR_SELECTED_FILE] = fileId; } else { ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); } }
Example 10
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 11
Source File: Gpg.java From OpenPGP-Card with GNU General Public License v3.0 | 5 votes |
/** * VERIFY APDU implementation. */ private void verify(APDU apdu) { byte buffer[] = apdu.getBuffer(); if (buffer[ISO7816.OFFSET_P1] != (byte) 0) { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } // type = 0x81 or 0x82 -> PIN1, min length = 6 // type = 0x83 -> PIN2, min length = 8 byte pinOffset = PIN_INDEX_PW1; byte type = buffer[ISO7816.OFFSET_P2]; byte minLength = MIN_PIN1_LENGTH; if (type == (byte) 0x83) { pinOffset = PIN_INDEX_PW3; minLength = MIN_PIN3_LENGTH; } else if (type != (byte) 0x81 && type != (byte) 0x82) { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } short length = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF); if (apdu.setIncomingAndReceive() != length || length > MAX_PIN_LENGTH || length < minLength) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (pins[pinOffset].getTriesRemaining() == 0) { ISOException.throwIt(SW_PIN_BLOCKED); } boolean result = pins[pinOffset].check(buffer, ISO7816.OFFSET_CDATA, (byte) length); if (type != (byte) 0x83) { pinSubmitted[(byte) (type - 0x81)] = result; } if (result) { ISOException.throwIt(ISO7816.SW_NO_ERROR); } ISOException.throwIt((short) (SW_PIN_FAILED_00 + pins[pinOffset].getTriesRemaining())); }
Example 12
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 13
Source File: LedgerWalletApplet.java From ledger-javacard with GNU Affero General Public License v3.0 | 4 votes |
private static void handleHashTransaction(APDU apdu) throws ISOException { byte[] buffer = apdu.getBuffer(); byte p1 = buffer[ISO7816.OFFSET_P1]; byte p2 = buffer[ISO7816.OFFSET_P2]; short dataOffset = (short)0; apdu.setIncomingAndReceive(); if (p1 == P1_HASH_TRANSACTION_FIRST) { TC.clear(); TC.ctx[TC.TX_B_TRANSACTION_STATE] = Transaction.STATE_NONE; TC.ctx[TC.TX_B_HASH_OPTION] = Transaction.HASH_BOTH; TC.ctx[TC.TX_Z_CHANGE_ACCEPTED] = (byte)0x01; } else if (p1 != P1_HASH_TRANSACTION_NEXT) { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } if (p2 == P2_HASH_TRANSACTION_NEW_INPUT) { if (p1 == P1_HASH_TRANSACTION_FIRST) { checkAccess(true); TC.ctxP[TC.P_TX_Z_WIRED] = (isContactless() ? TC.FALSE : TC.TRUE); TC.ctxP[TC.P_TX_Z_FIRST_SIGNED] = TC.TRUE; TC.ctxP[TC.P_TX_Z_RELAXED] = TC.FALSE; TC.ctxP[TC.P_TX_Z_CONSUME_P2SH] = TC.FALSE; TC.ctxP[TC.P_TX_Z_USE_KEYCARD] = TC.FALSE; Crypto.random.generateData(TC.ctxP, TC.P_TX_A_NONCE, TC.SIZEOF_NONCE); } } else if (p2 != P2_HASH_TRANSACTION_CONTINUE_INPUT) { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } checkInterfaceConsistency(); short remainingData = (short)((short)(buffer[ISO7816.OFFSET_LC] & 0xff) - dataOffset); byte result = Transaction.parseTransaction(Transaction.PARSE_SIGNATURE, buffer, (short)(ISO7816.OFFSET_CDATA + dataOffset), remainingData); if (result == Transaction.RESULT_ERROR) { ISOException.throwIt(ISO7816.SW_WRONG_DATA); } else if (result == Transaction.RESULT_MORE) { return; } else if (result == Transaction.RESULT_FINISHED) { return; } }
Example 14
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 15
Source File: TransitApplet.java From JCMathLib with MIT License | 4 votes |
/** * Processes an incoming request. The request message signature is verified, * then it is dispatched to the relevant handling method. The response * message is then signed and sent back. * * @param apdu * The APDU */ private void processRequest(APDU apdu) { // C-APDU: [CLA, INS, P1, P2, LC, [Request Message], [8-bytes MAC]] // Request Message: [T, L, [V...]] byte[] buffer = apdu.getBuffer(); if ((buffer[ISO7816.OFFSET_P1] != 0) || (buffer[ISO7816.OFFSET_P2] != 0)) { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } byte numBytes = buffer[ISO7816.OFFSET_LC]; byte count = (byte) apdu.setIncomingAndReceive(); if (numBytes != count) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } // Check request message signature if (!checkMAC(buffer)) { ISOException.throwIt(SW_WRONG_SIGNATURE); } if ((numBytes - MAC_LENGTH) != (buffer[TLV_LENGTH_OFFSET] + 2)) { ISOException.throwIt(ISO7816.SW_WRONG_DATA); } // R-APDU: [[Response Message], [2-bytes Status Word], [8-bytes MAC]] short offset = 0; // Dispatch request message for processing switch (buffer[TLV_TAG_OFFSET]) { case PROCESS_ENTRY: offset = processEntry(buffer, TLV_VALUE_OFFSET, buffer[TLV_LENGTH_OFFSET]); break; case PROCESS_EXIT: offset = processExit(buffer, TLV_VALUE_OFFSET, buffer[TLV_LENGTH_OFFSET]); break; case CREDIT: offset = credit(buffer, TLV_VALUE_OFFSET, buffer[TLV_LENGTH_OFFSET]); break; case GET_BALANCE: offset = getBalance(buffer, TLV_VALUE_OFFSET, buffer[TLV_LENGTH_OFFSET]); break; default: ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); } // Append status word to response message offset = Util.setShort(buffer, offset, SW_SUCCESS); // Sign response message and append MAC to response message offset = generateMAC(buffer, offset); // Send R-APDU apdu.setOutgoingAndSend((short) 0, offset); }
Example 16
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 17
Source File: TransitApplet.java From JCMathLib with MIT License | 4 votes |
/** * Initializes a CAD/card interaction session. This is the first step of * mutual authentication. A new card challenge is generated and used along * with the passed-in host challenge to generate the derivation data from * which a new session key is derived. The card challenge is appended to the * response message. The response message is signed using the newly * generated session key then sent back. Note that mutual authentication is * subsequently completed upon succesful verification of the signature of * the first request received. * * @param apdu * The APDU */ private void initializeSession(APDU apdu) { // C-APDU: [CLA, INS, P1, P2, LC, [4-bytes Host Challenge]] byte[] buffer = apdu.getBuffer(); if ((buffer[ISO7816.OFFSET_P1] != 0) || (buffer[ISO7816.OFFSET_P2] != 0)) { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } byte numBytes = buffer[ISO7816.OFFSET_LC]; byte count = (byte) apdu.setIncomingAndReceive(); if (numBytes != CHALLENGE_LENGTH || count != CHALLENGE_LENGTH) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } // Generate card challenge generateCardChallenge(); // Generate key derivation data from host challenge and card challenge generateKeyDerivationData(buffer); // Generate session key from derivation data generateSessionKey(); // R-APDU: [[4-bytes Card Challenge], [2-bytes Status Word], [8-bytes // MAC]] short offset = 0; // Append card challenge to response message offset = Util.arrayCopyNonAtomic(cardChallenge, (short) 0, buffer, offset, CHALLENGE_LENGTH); // Append status word to response message offset = Util.setShort(buffer, offset, SW_SUCCESS); // Sign response message and append MAC to response message offset = generateMAC(buffer, offset); // Send R-APDU apdu.setOutgoingAndSend((short) 0, offset); }
Example 18
Source File: CardAgent.java From CardExamples with The Unlicense | 4 votes |
/** * Handle Read Record command. * * @param apdu * the incoming <code>APDU</code> object */ private void readRecord(APDU apdu) throws ISOException { byte[] apduBuffer = apdu.getBuffer(); // DEBUG Log.v(LOG_TAG, "C-APDU: " + DataUtil.byteArrayToHexString(apduBuffer, 0, 5)); final byte recordNumber = apduBuffer[ISO7816.OFFSET_P1]; // Check P1/P2. if ((recordNumber == (byte) 0x00) || ((apduBuffer[ISO7816.OFFSET_P2] & (byte) 0x07) != (byte) 0x04)) { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } // Check if Lc is not present. // Check if Le=0x00. if ((apdu.setIncomingAndReceive() != (short) 0) || (apdu.setOutgoing() != (short) 256)) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } // Check if AFL saved in Get Processing Options or // if Read Records counter is greater than number of records indicated in AFL. if ((this.afl == null) || (this.readRecordCounter > this.aflRecords)) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } // Check if SFI and record supported in AFL. final byte sfi = (byte) ((apduBuffer[ISO7816.OFFSET_P2] & (byte) 0xF8)); boolean aflSupported = false; this.afl.reset(); while (this.afl.hasRemaining()) { byte aflSfi = this.afl.get(); byte aflFirstRecord = this.afl.get(); byte aflLastRecord = this.afl.get(); if ((aflSfi == sfi) && (aflFirstRecord <= recordNumber) && (aflLastRecord >= recordNumber)) { aflSupported = true; break; } // Skip the next byte. this.afl.get(); } if (!aflSupported) { Log.e(LOG_TAG, "Transaction Failure: SFI and record not supported in AFL."); ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); } // Retrieve record. short sfiRecord = (short) ((sfi << 5) | recordNumber); byte[] recordData = this.accountParamsStatic.getSfiRecord(sfiRecord); if (recordData == null) { if (sfiRecord == (short) 0x0204) { recordData = this.dynamicSfi2Record4; } else { // Req 7.23 Log.e(LOG_TAG, "Transaction Failure: SFI and record not found."); ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); } } // Increment Read Record counter. this.readRecordCounter++; // Copy record data to APDU response buffer. short rdataLength = (short) recordData.length; System.arraycopy(recordData, 0, apduBuffer, 0, rdataLength); // Determine if this is the last Read Record command. if (this.readRecordCounter == this.aflRecords) { this.apduState = APDU_SENDING_LAST; } else { this.apduState = APDU_SENDING; } // DEBUG Log.v(LOG_TAG, "R-APDU: " + DataUtil.byteArrayToHexString(apduBuffer, 0, rdataLength) + "9000"); apdu.setOutgoingLength(rdataLength); apdu.sendBytes((short) 0, rdataLength); // Determine if this is the last Read Record command. if (this.readRecordCounter == this.aflRecords) { // Success triggers a successful transaction. apdu.setTransactionSuccess(); } }
Example 19
Source File: IsoApplet.java From IsoApplet with GNU General Public License v3.0 | 4 votes |
/** * \brief Process the RESET RETRY COUNTER apdu (INS = 2C). * * This is used to unblock the PIN with the PUK and set a new PIN value. * * \param apdu The RESET RETRY COUNTER apdu. * * \throw ISOException SW_COMMAND_NOT_ALLOWED, ISO7816.SW_WRONG_LENGTH, SW_INCORRECT_P1P2, * SW_PIN_TRIES_REMAINING. */ public void processResetRetryCounter(APDU apdu) throws ISOException { byte[] buf = apdu.getBuffer(); byte p1 = buf[ISO7816.OFFSET_P1]; byte p2 = buf[ISO7816.OFFSET_P2]; short lc; short offset_cdata; if(state != STATE_OPERATIONAL_ACTIVATED) { ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED); } // Bytes received must be Lc. lc = apdu.setIncomingAndReceive(); if(lc != apdu.getIncomingLength()) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } offset_cdata = apdu.getOffsetCdata(); // Length of data field. if(lc < (short)(PUK_LENGTH + PIN_MIN_LENGTH) || lc > (short)(PUK_LENGTH + PIN_MAX_LENGTH)) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } // We expect the PUK followed by a new PIN. if(p1 != (byte) 0x00 || p2 != (byte) 0x01) { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } // Check the PUK. if(puk == null) { ISOException.throwIt(SW_PIN_TRIES_REMAINING); } else if (!puk.check(buf, offset_cdata, PUK_LENGTH)) { ISOException.throwIt((short)(SW_PIN_TRIES_REMAINING | puk.getTriesRemaining())); } else { // If we're here, the PUK was correct. // Pad the new PIN, if not done by caller. We don't want any gargabe from the APDU buffer to be part of the new PIN. Util.arrayFillNonAtomic(buf, (short)(offset_cdata + lc), (short)(PUK_LENGTH + PIN_MAX_LENGTH - lc), (byte) 0x00); // Set the PIN. pin.update(buf, (short)(offset_cdata+PUK_LENGTH), PIN_MAX_LENGTH); pin.resetAndUnblock(); } }
Example 20
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 4 votes |
/** * This function returns the public key associated with a particular private key stored * in the applet. The exact key blob contents depend on the key�s algorithm and type. * * ins: 0x35 * p1: private key number (0x00-0x0F) * p2: 0x00 * data: none * return(SECP256K1): [coordx_size(2b) | pubkey_coordx | sig_size(2b) | sig] */ private short getPublicKeyFromPrivate(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); 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); // check the curve param if(!Secp256k1.checkCurveParameters((ECPrivateKey)key, recvBuffer, (short)0)) ISOException.throwIt(SW_INCORRECT_ALG); // compute the corresponding partial public key... keyAgreement.init((ECPrivateKey)key); short coordx_size=(short)32; keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, buffer, (short)1); //pubkey in uncompressed form Util.setShort(buffer, (short)0, coordx_size); // sign fixed message sigECDSA.init(key, 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); // 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... return (short)(2+coordx_size+2+sign_size); }