Java Code Examples for javacard.framework.ISO7816#OFFSET_LC

The following examples show how to use javacard.framework.ISO7816#OFFSET_LC . 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: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 9 votes vote down vote up
/**
 * Store the incoming APDU data in a fixed buffer, the first byte will contain the data length.
 *
 * @param pin_type indicates which PIN should be checked.
 */
void storeVariableLength(APDU apdu, byte[] destination, short pin_type) {
  byte[] buffer = apdu.getBuffer();
  // When writing DOs, PW1 really means PW1 submitted as PW2.
  if (!pins[pin_type].isValidated() ||
      ((pin_type == PIN_INDEX_PW1) && !pinSubmitted[1])) {
    ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
  }
  short length = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
  if ((short) (length + 1) > destination.length || length > (short) 255 ||
      apdu.setIncomingAndReceive() != length) {
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  }
  JCSystem.beginTransaction();
  destination[0] = (byte) length;
  Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, destination, (short) 1, length);
  JCSystem.commitTransaction();
}
 
Example 2
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 7 votes vote down vote up
private void internalAuthenticate(APDU apdu) {
  byte[] buffer = apdu.getBuffer();
  // PW1 with 0x82
  if (!pins[PIN_INDEX_PW1].isValidated() || !pinSubmitted[1]) {
    ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
  }
  short len = apdu.setIncomingAndReceive();
  if (len > (short) 102 || len != (buffer[ISO7816.OFFSET_LC] & 0xFF)) {
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  }
  if (!authenticationKey.getPrivate().isInitialized()) {
    ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
  }
  cipherRSA.init(authenticationKey.getPrivate(), Cipher.MODE_ENCRYPT);
  cipherRSA.doFinal(buffer, ISO7816.OFFSET_CDATA, len, buffer, (short) 0);
  apdu.setOutgoingAndSend((short) 0, RSA_KEY_LENGTH_BYTES);
}
 
Example 3
Source File: TransitApplet.java    From JCMathLib with MIT License 6 votes vote down vote up
/**
 * Verifies the PIN.
 * 
 * @param apdu
 *            The APDU
 */
private void verify(APDU apdu) {

    byte[] buffer = apdu.getBuffer();

    byte numBytes = buffer[ISO7816.OFFSET_LC];

    byte count = (byte) apdu.setIncomingAndReceive();

    if (numBytes != count) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // Verify PIN
    if (pin.check(buffer, ISO7816.OFFSET_CDATA, numBytes) == false) {
        ISOException.throwIt(SW_VERIFICATION_FAILED);
    }
}
 
Example 4
Source File: TransitApplet.java    From JCMathLib with MIT License 6 votes vote down vote up
/**
 * Generates the session key derivation data from the passed-in host
 * challenge and the card challenge.
 * 
 * @param buffer
 *            The APDU buffer
 */
private void generateKeyDerivationData(byte[] buffer) {
    byte numBytes = buffer[ISO7816.OFFSET_LC];

    if (numBytes < CHALLENGE_LENGTH) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // Derivation data: [[8-bytes host challenge], [8-bytes card challenge]]

    // Append host challenge (from buffer) to derivation data
    Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, keyDerivationData,
            (short) 0, CHALLENGE_LENGTH);
    // Append card challenge to derivation data
    Util.arrayCopy(cardChallenge, (short) 0, keyDerivationData,
            CHALLENGE_LENGTH, CHALLENGE_LENGTH);
}
 
Example 5
Source File: TransitApplet.java    From JCMathLib with MIT License 6 votes vote down vote up
/**
 * Checks the request message signature.
 * 
 * @param buffer
 *            The APDU buffer
 * @return true if the message signature is correct; false otherwise
 */
private boolean checkMAC(byte[] buffer) {
    byte numBytes = buffer[ISO7816.OFFSET_LC];

    if (numBytes <= MAC_LENGTH) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // Initialize signature with current session key for verification
    signature.init(sessionKey, Signature.MODE_VERIFY);
    // Verify request message signature
    return signature.verify(buffer, ISO7816.OFFSET_CDATA,
            (short) (numBytes - MAC_LENGTH), buffer,
            (short) (ISO7816.OFFSET_CDATA + numBytes - MAC_LENGTH),
     MAC_LENGTH);
}
 
Example 6
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 6 votes vote down vote up
/**
 * 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 7
Source File: GaussKeyCard.java    From gauss-key-card with Apache License 2.0 6 votes vote down vote up
private void
processAuthenticate(APDU apdu)
{
	final byte[] buffer = apdu.getBuffer();
	final short incomingLength = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);

	if (incomingLength < (short)0x51) {
		ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
	}

	ecdh.generateSecret(buffer, ISO7816.OFFSET_CDATA, (short)65, buffer, (short)16);

	aes_key.setKey(buffer, (short)16);
	aes_ecb.init(aes_key, Cipher.MODE_ENCRYPT);

	// Generate the random salt.
	rng.generateData(buffer, OFFSET_CHALLENGE, (short)4);

	short len = aes_ecb.doFinal(buffer, OFFSET_CHALLENGE, (short)16, buffer, (short)0);
	final short le = apdu.setOutgoing();

	len = le > 0 ? (le > len ? len : le) : len;
	apdu.setOutgoingLength(len);
	apdu.sendBytes((short)0, len);
}
 
Example 8
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 6 votes vote down vote up
private static void handleAdmSetKeycardSeed(APDU apdu, boolean airgap) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    short offset = ISO7816.OFFSET_CDATA;
    byte keyLength;
    apdu.setIncomingAndReceive();
    if ((setup == TC.TRUE) || (setup != TC.FALSE)) {
        ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }
    if (buffer[ISO7816.OFFSET_LC] != (byte)(KEYCARD_KEY_LENGTH + 1)) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    if ((buffer[offset] == (byte)0) || (buffer[offset] > TC.MAX_KEYCARD_DIGIT_ADDRESS)) {
        ISOException.throwIt(ISO7816.SW_WRONG_DATA);
    }
    if (!airgap) {
        Keycard.setIssuer(buffer[offset], buffer, (short)(offset + 1));
    }
    else {
        Crypto.initCipherAES(pairingKey, false);
        Crypto.blobEncryptDecryptAES.doFinal(buffer, (short)(offset + 1), (short)16, scratch256, (short)0);
        Keycard.setIssuer(buffer[offset], scratch256, (short)0);
    }
}
 
Example 9
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 6 votes vote down vote up
private static void handleVerifyPin(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    if ((setup == TC.FALSE) || (setup != TC.TRUE)) {
        ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }
    if (buffer[ISO7816.OFFSET_P1] == P1_GET_REMAINING_ATTEMPTS) {
     buffer[0] = walletPin.getTriesRemaining();
     apdu.setOutgoingAndSend((short)0, (short)1);
     return;
    }
    apdu.setIncomingAndReceive();
    if (buffer[ISO7816.OFFSET_LC] != walletPinSize) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    Util.arrayFillNonAtomic(scratch256, (short)0, WALLET_PIN_SIZE, (byte)0xff);
    Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, scratch256, (short)0, walletPinSize);
    if (!walletPin.check(scratch256, (short)0, WALLET_PIN_SIZE)) {
        if (walletPin.getTriesRemaining() == 0) {
            reset();
        }
        ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
    }
}
 
Example 10
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 5 votes vote down vote up
/**
 * RESET RETRY COUNTER ADPU implementation.
 */
private void resetRetryCounter(APDU apdu) {
  byte buffer[] = apdu.getBuffer();
  short length = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
  if (apdu.setIncomingAndReceive() != length) {
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  }

  if (buffer[ISO7816.OFFSET_P2] != (byte) 0x81) {
    ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
  }
  if (buffer[ISO7816.OFFSET_P1] == (byte) 0) {
    // We need to check RC then update P1 (if RC is set).
    byte rcLength = pinLength[PIN_INDEX_RC];
    if (pins[PIN_INDEX_RC].getTriesRemaining() == 0 || rcLength == 0) {
      ISOException.throwIt(SW_PIN_BLOCKED);
    }
    if (length < rcLength + MIN_PIN1_LENGTH ||
        length > rcLength + MAX_PIN_LENGTH) {
      ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    if (pins[PIN_INDEX_RC].check(buffer, ISO7816.OFFSET_CDATA, rcLength)) {
      updatePIN(PIN_INDEX_PW1, buffer, (short) (ISO7816.OFFSET_CDATA + rcLength),
                (byte) (length - rcLength));
    } else {
      ISOException.throwIt((short) (SW_PIN_FAILED_00 + pins[PIN_INDEX_RC].getTriesRemaining()));
    }
  } else if (buffer[ISO7816.OFFSET_P1] == (byte) 2) {
    // Resetting by assuming that PW3 was submitted.
    if (!pins[PIN_INDEX_PW3].isValidated()) {
      ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }
    if (length < MIN_PIN1_LENGTH || length > MAX_PIN_LENGTH) {
      ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    updatePIN(PIN_INDEX_PW1, buffer, ISO7816.OFFSET_CDATA, (byte) length);
  } else {
    ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
  }
}
 
Example 11
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 5 votes vote down vote up
/**
 * 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 12
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 5 votes vote down vote up
/**
 * 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 13
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Terminate DF is only valid if PW1 and PW3 are blocked.
 * @param apdu
 */
private void terminateDF(APDU apdu) {
  byte[] buffer = apdu.getBuffer();
  if (buffer[ISO7816.OFFSET_LC] != 0) {
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  }
  if (pins[PIN_INDEX_PW1].getTriesRemaining() > 0 ||
      pins[PIN_INDEX_PW3].getTriesRemaining() > 0) {
    ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
  }
  terminated = true;
}
 
Example 14
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 5 votes vote down vote up
private static void handleSetContactlessLimit(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    apdu.setIncomingAndReceive();
    if (isContactless()) {
        ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }
    if (buffer[ISO7816.OFFSET_LC] != LIMIT_LAST) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, limits, (short)0, LIMIT_LAST);
    if (limitsSet != TC.TRUE) {
        limitsSet = TC.TRUE;
    }
}
 
Example 15
Source File: Ppse2Pay.java    From CardExamples with The Unlicense 4 votes vote down vote up
@Override
public void process(APDU apdu) throws ISOException {
    byte[] buf = apdu.getBuffer();

    if (selectingApplet()) {
        //check that LC is 0x0E
        if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != 0x0E)
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

        //get the rest of the apdu and check length
        if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != apdu.setIncomingAndReceive())
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

        if(FCI_TEMPLATE==null)
        {
            FCI_TEMPLATE = new byte[12 + ADF.length];
            FCI_TEMPLATE[0]=(byte)0xA5; //FCI Proprietary Template
            FCI_TEMPLATE[1]=(byte)(10 + ADF.length);   //length
            FCI_TEMPLATE[2]=(byte)0xBF; //FCI Issuer Discretionary Data
            FCI_TEMPLATE[3]=(byte)0x0C;
            FCI_TEMPLATE[4]=(byte)(7 + ADF.length);   //length

            FCI_TEMPLATE[5]=(byte)0x61; //Directory Entry
            FCI_TEMPLATE[6]=(byte)(ADF.length + 5);   //length
            FCI_TEMPLATE[7]=(byte)0x4F; //ADF Name
            FCI_TEMPLATE[8]=(byte)(ADF.length);    //length
            for(short i=0;i<ADF.length;i++)
                FCI_TEMPLATE[9+i] = ADF[i];
            FCI_TEMPLATE[9 + ADF.length]=(byte)0x87; //Application Priority Indicator
            FCI_TEMPLATE[10 + ADF.length]=(byte)1;    //length
            FCI_TEMPLATE[11 + ADF.length]=(byte)0x01;
        }

        //return FCI upon successful select
        apdu.setOutgoing();

        buf[0]=(byte)0x6F; //FCI Template
        buf[1]=(byte)(2 + DF.length + FCI_TEMPLATE.length);   //length
        buf[2]=(byte)0x84; //DF Name
        buf[3]=(byte)DF.length;   //length
        for(short i=0;i<DF.length;i++)
            buf[4+i] = DF[i];
        for(short i=0;i<FCI_TEMPLATE.length;i++)
            buf[4 + DF.length + i] = FCI_TEMPLATE[i];
        apdu.setOutgoingLength((short)(4 + DF.length + FCI_TEMPLATE.length));
        apdu.sendBytes((short)0,(short)(4 + DF.length + FCI_TEMPLATE.length));
        return;
    }

    switch (buf[ISO7816.OFFSET_INS]) {

        case (byte) 0xA4: //select PPSE
            //check that P1 & P2 are correct
            if(buf[ISO7816.OFFSET_P1] != (byte) 0x04 || buf[ISO7816.OFFSET_P2] != (byte) 0x00)
                ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);

            //check that LC is 0x0E
            if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != 0x0E)
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

            //get the rest of the apdu and check length
            if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != apdu.setIncomingAndReceive())
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
                //otherwise, the file name was wrong for this select
            else ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);

        case (byte) 0xEE: //loopback
            //check that P1 & P2 are correct
            if(buf[ISO7816.OFFSET_P1] != (byte) 0x00 || buf[ISO7816.OFFSET_P2] != (byte) 0x00)
                ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);

            //check that the length byte is within the spec (1-250)
            if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) < 1 || (short)(buf[ISO7816.OFFSET_LC] & 0xFF) > 250)
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

            //get the rest of the apdu and check length
            if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != apdu.setIncomingAndReceive())
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

            short len = buf[ISO7816.OFFSET_LC];
            for(short i=0;i<len;i++)
                buf[i] = buf[i+5];
            apdu.setOutgoingLength(len);
            apdu.sendBytes((short)0,len);
            break;

        default:
            // good practice: If you don't know the INStruction, say so:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
    }


}
 
Example 16
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
private static void handleSetUserKeycard(APDU apdu, boolean airgap) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    short offset = ISO7816.OFFSET_CDATA;
    apdu.setIncomingAndReceive();
    if ((setup == TC.FALSE) || (setup != TC.TRUE)) {
        ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }
    if (Keycard.issuerKeycardSize == (byte)0) {
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }
    if (buffer[ISO7816.OFFSET_P1] == P1_SET_KEYCARD) {
        if (buffer[ISO7816.OFFSET_LC] != (byte)(KEYCARD_KEY_LENGTH + 1)) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
        Keycard.setPairingData(buffer, ISO7816.OFFSET_CDATA);
        Keycard.generateRandomIndexes(Keycard.challenge, (short)0, KEYCARD_CHALLENGE_LENGTH);
        buffer[0] = CONFIRM_PREVIOUS_KEYCARD;
        Util.arrayCopyNonAtomic(Keycard.challenge, (short)0, buffer, (short)1, KEYCARD_CHALLENGE_LENGTH);
        apdu.setOutgoingAndSend((short)0, (short)(KEYCARD_CHALLENGE_LENGTH + 1));
    }
    else
    if (buffer[ISO7816.OFFSET_P1] == P1_CONFIRM_KEYCARD) {
        if (buffer[ISO7816.OFFSET_LC] != KEYCARD_CHALLENGE_LENGTH) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
        if (!Keycard.check(null, (short)0, (byte)0,
               buffer, ISO7816.OFFSET_CDATA, (byte)4,
               Keycard.challenge, (short)0,
               scratch256, (short)150)) {
            Keycard.clearPairingData();
            ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
        }
        else {
            Keycard.getPairingData(scratch256, (short)0);
            if (!airgap) {
                Keycard.setUser(scratch256[0], scratch256, (short)1);
            }
            else {
                Crypto.initCipherAES(pairingKey, false);
                Crypto.blobEncryptDecryptAES.doFinal(scratch256, (short)1, (short)16, scratch256, (short)100);
                Keycard.setUser(scratch256[0], scratch256, (short)100);
            }
        }
    }
    else {
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }
}
 
Example 17
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 4 votes vote down vote up
/**
 * The PUT DATA APDU implementation.
 */
private void putData(APDU apdu) {
  byte[] buffer = apdu.getBuffer();
  short length = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
  short tag = Util.getShort(buffer, ISO7816.OFFSET_P1);
  switch (tag) {
    // Private use objects.
    case 0x101:
      storeVariableLength(apdu, privateDO1, PIN_INDEX_PW1);
      break;

    case 0x102:
      storeVariableLength(apdu, privateDO2, PIN_INDEX_PW3);
      break;

    case 0x103:
      storeVariableLength(apdu, privateDO3, PIN_INDEX_PW1);
      break;

    case 0x104:
      storeVariableLength(apdu, privateDO4, PIN_INDEX_PW3);
      break;

    case 0x5B:
      storeVariableLength(apdu, name, PIN_INDEX_PW3);
      break;

    case 0x5E:
      storeVariableLength(apdu, loginData, PIN_INDEX_PW3);
      break;

    case 0x5F2D:
      storeVariableLength(apdu, language, PIN_INDEX_PW3);
      break;

    case 0x5F35:
      storeFixedLength(apdu, sex, (short) 0, (short) 1);
      break;

    case 0x5F50:
      storeVariableLength(apdu, url, PIN_INDEX_PW3);
      break;

    case 0xC4:
      if (!pins[PIN_INDEX_PW3].isValidated()) {
        ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
      }
      if (length < (short) 1 || length > (short) 8 || length != apdu.setIncomingAndReceive()) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
      }
      pinValidForMultipleSignatures = buffer[ISO7816.OFFSET_CDATA];
      break;

    case 0xC7:
    case 0xC8:
    case 0xC9:
      storeFixedLength(apdu, fingerprints, (short) (20 * (tag - 0xC7)), (short) 20);
      break;

    case 0xCA:
    case 0xCB:
    case 0xCC:
      storeFixedLength(apdu, caFingerprints, (short) (20 * (tag - 0xCA)), (short) 20);
      break;

    case 0xCE:
    case 0xCF:
    case 0xD0:
      storeFixedLength(apdu, generationDates, (short) (4 * (tag - 0xCE)), (short) 4);
      break;

    case 0xD3:
      storeVariableLength(apdu, buffer, PIN_INDEX_PW3);
      // Reset code must be zero or 8 - MAX_PIN_LENGTH.
      if (length > MAX_PIN_LENGTH || (length != (byte) 0 && length < (byte) 8)) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
      }
      updatePIN(PIN_INDEX_RC, buffer, (short) 1, buffer[0]);
      break;

    default:
      ISOException.throwIt(ISO7816.SW_RECORD_NOT_FOUND);
  }
}
 
Example 18
Source File: ECTesterApplet.java    From ECTester with MIT License 4 votes vote down vote up
short getIncomingLength(APDU apdu) {
    byte[] apduBuffer = apdu.getBuffer();
    return (short) (0xff & apduBuffer[ISO7816.OFFSET_LC]);
}
 
Example 19
Source File: TransitApplet.java    From JCMathLib with MIT License 4 votes vote down vote up
/**
 * 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 20
Source File: Ppse2Pay.java    From CardExamples with The Unlicense 4 votes vote down vote up
@Override
public void process(APDU apdu) throws ISOException {
    byte[] buf = apdu.getBuffer();

    if (selectingApplet()) {
        //check that LC is 0x0E
        if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != 0x0E)
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

        //get the rest of the apdu and check length
        if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != apdu.setIncomingAndReceive())
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

        if(FCI_TEMPLATE==null)
        {
            FCI_TEMPLATE = new byte[12 + ADF.length];
            FCI_TEMPLATE[0]=(byte)0xA5; //FCI Proprietary Template
            FCI_TEMPLATE[1]=(byte)(10 + ADF.length);   //length
            FCI_TEMPLATE[2]=(byte)0xBF; //FCI Issuer Discretionary Data
            FCI_TEMPLATE[3]=(byte)0x0C;
            FCI_TEMPLATE[4]=(byte)(7 + ADF.length);   //length

            FCI_TEMPLATE[5]=(byte)0x61; //Directory Entry
            FCI_TEMPLATE[6]=(byte)(ADF.length + 5);   //length
            FCI_TEMPLATE[7]=(byte)0x4F; //ADF Name
            FCI_TEMPLATE[8]=(byte)(ADF.length);    //length
            for(short i=0;i<ADF.length;i++)
                FCI_TEMPLATE[9+i] = ADF[i];
            FCI_TEMPLATE[9 + ADF.length]=(byte)0x87; //Application Priority Indicator
            FCI_TEMPLATE[10 + ADF.length]=(byte)1;    //length
            FCI_TEMPLATE[11 + ADF.length]=(byte)0x01;
        }

        //return FCI upon successful select
        apdu.setOutgoing();

        buf[0]=(byte)0x6F; //FCI Template
        buf[1]=(byte)(2 + DF.length + FCI_TEMPLATE.length);   //length
        buf[2]=(byte)0x84; //DF Name
        buf[3]=(byte)DF.length;   //length
        for(short i=0;i<DF.length;i++)
            buf[4+i] = DF[i];
        for(short i=0;i<FCI_TEMPLATE.length;i++)
            buf[4 + DF.length + i] = FCI_TEMPLATE[i];
        apdu.setOutgoingLength((short)(4 + DF.length + FCI_TEMPLATE.length));
        apdu.sendBytes((short)0,(short)(4 + DF.length + FCI_TEMPLATE.length));
        return;
    }

    switch (buf[ISO7816.OFFSET_INS]) {

        case (byte) 0xA4: //select PPSE
            //check that P1 & P2 are correct
            if(buf[ISO7816.OFFSET_P1] != (byte) 0x04 || buf[ISO7816.OFFSET_P2] != (byte) 0x00)
                ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);

            //check that LC is 0x0E
            if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != 0x0E)
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

            //get the rest of the apdu and check length
            if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != apdu.setIncomingAndReceive())
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
                //otherwise, the file name was wrong for this select
            else ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);

        case (byte) 0xEE: //loopback
            //check that P1 & P2 are correct
            if(buf[ISO7816.OFFSET_P1] != (byte) 0x00 || buf[ISO7816.OFFSET_P2] != (byte) 0x00)
                ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);

            //check that the length byte is within the spec (1-250)
            if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) < 1 || (short)(buf[ISO7816.OFFSET_LC] & 0xFF) > 250)
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

            //get the rest of the apdu and check length
            if((short)(buf[ISO7816.OFFSET_LC] & 0xFF) != apdu.setIncomingAndReceive())
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

            short len = buf[ISO7816.OFFSET_LC];
            for(short i=0;i<len;i++)
                buf[i] = buf[i+5];
            apdu.setOutgoingLength(len);
            apdu.sendBytes((short)0,len);
            break;

        default:
            // good practice: If you don't know the INStruction, say so:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
    }


}