Java Code Examples for javacard.framework.APDU#setIncomingAndReceive()

The following examples show how to use javacard.framework.APDU#setIncomingAndReceive() . 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: 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 3
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 4
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 5
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 5 votes vote down vote up
private static void handleStorePublicKey(APDU apdu) throws ISOException {
 byte[] buffer = apdu.getBuffer();
 apdu.setIncomingAndReceive();
 short offset = ISO7816.OFFSET_CDATA;
 byte derivationSize = buffer[offset++];
 byte i;
 if (Crypto.keyAgreement == null) {
  ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
 }
 if (derivationSize > MAX_DERIVATION_PATH) {
  ISOException.throwIt(ISO7816.SW_DATA_INVALID);
 }
    Crypto.initCipher(chipKey, false);
    Crypto.blobEncryptDecrypt.doFinal(masterDerived, (short)0, (short)DEFAULT_SEED_LENGTH, scratch256, (short)0);
    i = Bip32Cache.copyPrivateBest(buffer, (short)(ISO7816.OFFSET_CDATA + 1), derivationSize, scratch256, (short)0);
    for (; i<derivationSize; i++) {
     Util.arrayCopyNonAtomic(buffer, (short)(offset + 4 * i), scratch256, Bip32.OFFSET_DERIVATION_INDEX, (short)4);
     if ((proprietaryAPI == null) && ((scratch256[Bip32.OFFSET_DERIVATION_INDEX] & (byte)0x80) == 0)) {
      if (!Bip32Cache.setPublicIndex(buffer, (short)(ISO7816.OFFSET_CDATA + 1), i)) {
       ISOException.throwIt(SW_PUBLIC_POINT_NOT_AVAILABLE);
      }
     }
     if (!Bip32.derive(buffer)) {
      ISOException.throwIt(ISO7816.SW_WRONG_DATA);
     }
     Bip32Cache.storePrivate(buffer, (short)(ISO7816.OFFSET_CDATA + 1), (byte)(i + 1), scratch256);
    }
    offset += (short)(derivationSize * 4);
    Crypto.random.generateData(scratch256, (short)32, (short)32);
    signTransientPrivate(scratch256, (short)0, scratch256, (short)32, scratch256, (short)64);
    if (Crypto.verifyPublic(buffer, offset, scratch256, (short)32, scratch256, (short)64)) {
     Bip32Cache.storePublic(buffer, (short)(ISO7816.OFFSET_CDATA + 1), derivationSize, buffer, offset);
    }
    else {
     ISOException.throwIt(ISO7816.SW_WRONG_DATA);
    }
}
 
Example 6
Source File: U2FApplet.java    From CCU2F with Apache License 2.0 5 votes vote down vote up
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 7
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 8
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 5 votes vote down vote up
private static void handleHasCachedPublicKey(APDU apdu) throws ISOException {
 byte[] buffer = apdu.getBuffer();
 apdu.setIncomingAndReceive();
 short offset = ISO7816.OFFSET_CDATA;
 byte derivationSize = buffer[offset++];
 if (derivationSize > MAX_DERIVATION_PATH) {
  ISOException.throwIt(ISO7816.SW_DATA_INVALID);
 }
 boolean result = Bip32Cache.hasPublic(buffer, offset, derivationSize);
 buffer[0] = (result ? (byte)0x01 : (byte)0x00);
 apdu.setOutgoingAndSend((short)0, (short)1);
}
 
Example 9
Source File: GidsPINManager.java    From GidsApplet with GNU General Public License v3.0 5 votes vote down vote up
/**
 * \brief Process the general authentication process
 */
public void processGeneralAuthenticate(APDU apdu) {
    byte[] buf = apdu.getBuffer();
    byte p1 = buf[ISO7816.OFFSET_P1];
    byte p2 = buf[ISO7816.OFFSET_P2];
    short lc;

    if(isInInitializationMode) {
        ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
    }

    if(p1 != (byte) 0x00 || p2 != (byte) 0x00 ) {
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }

    // Bytes received must be Lc.
    lc = apdu.setIncomingAndReceive();

    short innerPos = 0, innerLen = 0;
    if (buf[ISO7816.OFFSET_CDATA] != (byte) 0x7C) {
        ISOException.throwIt(ISO7816.SW_DATA_INVALID);
    }


    try {
        innerLen = UtilTLV.decodeLengthField(buf, (short) (ISO7816.OFFSET_CDATA+1));
        innerPos = (short) (ISO7816.OFFSET_CDATA + 1 + UtilTLV.getLengthFieldLength(buf, (short) (ISO7816.OFFSET_CDATA+1)));
    } catch (InvalidArgumentsException e1) {
        ISOException.throwIt(ISO7816.SW_DATA_INVALID);
    }

    // inner functions never return if their input tag is found
    if (CheckForExternalChallenge(apdu, buf, innerPos, innerLen)) {
        return;
    }
    if (CheckForChallengeResponse(apdu, buf, innerPos, innerLen)) {
        return;
    }
    ISOException.throwIt(ISO7816.SW_DATA_INVALID);
}
 
Example 10
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 5 votes vote down vote up
private static void handleHashSignDerive(APDU apdu, boolean checkStage) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    short offset = ISO7816.OFFSET_CDATA;
    byte i;
    apdu.setIncomingAndReceive();
    if (checkStage) {
        checkInterfaceConsistency();
        if (TC.ctx[TC.TX_B_TRANSACTION_STATE] != Transaction.STATE_SIGN_READY) {
            ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
        }
    }
    byte derivationSize = buffer[offset++];
    if (derivationSize > MAX_DERIVATION_PATH) {
        ISOException.throwIt(ISO7816.SW_DATA_INVALID);
    }
    Crypto.initCipher(chipKey, false);
    Crypto.blobEncryptDecrypt.doFinal(masterDerived, (short)0, (short)DEFAULT_SEED_LENGTH, scratch256, (short)0);
    i = Bip32Cache.copyPrivateBest(buffer, (short)(ISO7816.OFFSET_CDATA + 1), derivationSize, scratch256, (short)0);
    offset += (short)(i * 4);
    for (; i<derivationSize; i++) {
        Util.arrayCopyNonAtomic(buffer, offset, scratch256, Bip32.OFFSET_DERIVATION_INDEX, (short)4);
        if ((proprietaryAPI == null) && ((scratch256[Bip32.OFFSET_DERIVATION_INDEX] & (byte)0x80) == 0)) {
            if (!Bip32Cache.setPublicIndex(buffer, (short)(ISO7816.OFFSET_CDATA + 1), i)) {
                ISOException.throwIt(SW_PUBLIC_POINT_NOT_AVAILABLE);
            }
        }
        if (!Bip32.derive(buffer)) {
            ISOException.throwIt(ISO7816.SW_WRONG_DATA);
        }
        Bip32Cache.storePrivate(buffer, (short)(ISO7816.OFFSET_CDATA + 1), (byte)(i + 1), scratch256);
        offset += (short)4;
    }
}
 
Example 11
Source File: NdefApplet.java    From openjavacard-ndef with GNU General Public License v3.0 5 votes vote down vote up
/**
 * 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 12
Source File: NdefApplet.java    From openjavacard-ndef with GNU General Public License v3.0 5 votes vote down vote up
/**
 * 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 13
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 5 votes vote down vote up
private static void handleSetAttestationPublic(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    apdu.setIncomingAndReceive();
    checkAirgapPersonalizationAvailable();
    if (buffer[ISO7816.OFFSET_LC] != (byte)attestationPublic.length) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, attestationPublic, (short)0, (short)attestationPublic.length);
}
 
Example 14
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 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: IsoApplet.java    From IsoApplet with GNU General Public License v3.0 4 votes vote down vote up
/**
 * \brief Compute a digital signature of the data from the apdu
 * 			using the private key referenced by	an earlier
 *			MANAGE SECURITY ENVIRONMENT apdu.
 *
 * \attention The apdu should contain a hash, not raw data for RSA keys.
 * 				PKCS1 padding will be applied if neccessary.
 *
 * \param apdu The PERFORM SECURITY OPERATION apdu with P1=9E and P2=9A.
 *
 * \throw ISOException SW_CONDITIONS_NOT_SATISFIED, SW_WRONG_LENGTH
 * 						and SW_UNKNOWN.
 */
private void computeDigitalSignature(APDU apdu) throws ISOException {
    byte[] buf = apdu.getBuffer();
    short offset_cdata;
    short lc;
    short sigLen = 0;


    switch(currentAlgorithmRef[0]) {
    case ALG_RSA_PAD_PKCS1:
        // Receive.
        // Bytes received must be Lc.
        lc = apdu.setIncomingAndReceive();
        if(lc != apdu.getIncomingLength()) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
        offset_cdata = apdu.getOffsetCdata();

        // RSA signature operation.
        RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) keys[currentPrivateKeyRef[0]];

        if(lc > (short) 247) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }

        rsaPkcs1Cipher.init(rsaKey, Cipher.MODE_ENCRYPT);
        sigLen = rsaPkcs1Cipher.doFinal(buf, offset_cdata, lc, ram_buf, (short)0);

        if(sigLen != 256) {
            ISOException.throwIt(ISO7816.SW_UNKNOWN);
        }

        // A single short APDU can handle 256 bytes - only one send operation neccessary.
        short le = apdu.setOutgoing();
        if(le < sigLen) {
            ISOException.throwIt(ISO7816.SW_CORRECT_LENGTH_00);
        }
        apdu.setOutgoingLength(sigLen);
        apdu.sendBytesLong(ram_buf, (short) 0, sigLen);
        break;

    case ALG_ECDSA_SHA1:
        // Get the key - it must be a EC private key,
        // checks have been done in MANAGE SECURITY ENVIRONMENT.
        ECPrivateKey ecKey = (ECPrivateKey) keys[currentPrivateKeyRef[0]];

        // Initialisation should be done when:
        // 	- No command chaining is performed at all.
        //	- Command chaining is performed and this is the first apdu in the chain.
        if(ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] == (short) 0) {
            ecdsaSignature.init(ecKey, Signature.MODE_SIGN);
            if(isCommandChainingCLA(apdu)) {
                ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] = (short) 1;
            }
        }

        short recvLen = apdu.setIncomingAndReceive();
        offset_cdata = apdu.getOffsetCdata();

        // Receive data. For extended APDUs, the data is received piecewise
        // and aggregated in the hash. When using short APDUs, command
        // chaining is performed.
        while (recvLen > 0) {
            ecdsaSignature.update(buf, offset_cdata, recvLen);
            recvLen = apdu.receiveBytes(offset_cdata);
        }

        if(!isCommandChainingCLA(apdu)) {
            sigLen = ecdsaSignature.sign(buf, (short)0, (short)0, buf, (short) 0);
            ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] = (short) 0;
            apdu.setOutgoingAndSend((short) 0, sigLen);
        } else {
            ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS]++;
        }

        break;

    default:
        // Wrong/unknown algorithm.
        ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }
}
 
Example 17
Source File: IsoApplet.java    From IsoApplet with GNU General Public License v3.0 4 votes vote down vote up
/**
 * \brief Process the VERIFY apdu (INS = 20).
 *
 * This apdu is used to verify a PIN and authenticate the user. A counter is used
 * to limit unsuccessful tries (i.e. brute force attacks).
 *
 * \param apdu The apdu.
 *
 * \throw ISOException SW_INCORRECT_P1P2, ISO7816.SW_WRONG_LENGTH, SW_PIN_TRIES_REMAINING.
 */
private void processVerify(APDU apdu) throws ISOException {
    byte[] buf = apdu.getBuffer();
    short offset_cdata;
    short lc;

    // P1P2 0001 only at the moment. (key-reference 01 = PIN)
    if(buf[ISO7816.OFFSET_P1] != 0x00 || buf[ISO7816.OFFSET_P2] != 0x01) {
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }

    // Bytes received must be Lc.
    lc = apdu.setIncomingAndReceive();
    if(lc != apdu.getIncomingLength()) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    offset_cdata = apdu.getOffsetCdata();

    // Lc might be 0, in this case the caller checks if verification is required.
    if((lc > 0 && (lc < PIN_MIN_LENGTH) || lc > PIN_MAX_LENGTH)) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // Caller asks if verification is needed.
    if(lc == 0
            && state != STATE_CREATION
            && state != STATE_INITIALISATION) {
        // Verification required, return remaining tries.
        ISOException.throwIt((short)(SW_PIN_TRIES_REMAINING | pin.getTriesRemaining()));
    } else if(lc == 0
              && (state == STATE_CREATION
                  || state == STATE_INITIALISATION)) {
        // No verification required.
        ISOException.throwIt(ISO7816.SW_NO_ERROR);
    }

    // Pad the PIN if not done by caller, so no garbage from the APDU will be part of the PIN.
    Util.arrayFillNonAtomic(buf, (short)(offset_cdata + lc), (short)(PIN_MAX_LENGTH - lc), (byte) 0x00);

    // Check the PIN.
    if(!pin.check(buf, offset_cdata, PIN_MAX_LENGTH)) {
        fs.setUserAuthenticated(false);
        ISOException.throwIt((short)(SW_PIN_TRIES_REMAINING | pin.getTriesRemaining()));
    } else {
        fs.setUserAuthenticated(true);
    }
}
 
Example 18
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 19
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
private static void handleTrustedInput(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    byte p1 = buffer[ISO7816.OFFSET_P1];
    byte dataOffset = (short)0;
    apdu.setIncomingAndReceive();
    if (p1 == P1_TRUSTED_INPUT_FIRST) {
        Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, TC.ctx, TC.TX_I_TRANSACTION_TARGET_INPUT, TC.SIZEOF_U32);
        TC.ctx[TC.TX_B_TRANSACTION_STATE] = Transaction.STATE_NONE;
        TC.ctx[TC.TX_B_TRUSTED_INPUT_PROCESSED] = (byte)0x00;
        TC.ctx[TC.TX_B_HASH_OPTION] = Transaction.HASH_FULL;
        dataOffset = (short)4;
    }
    else
    if (p1 != P1_TRUSTED_INPUT_NEXT) {
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }
    short remainingData = (short)((short)(buffer[ISO7816.OFFSET_LC] & 0xff) - dataOffset);
    byte result = Transaction.parseTransaction(Transaction.PARSE_TRUSTED_INPUT, 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) {
        short offset = 0;
        buffer[offset++] = BLOB_MAGIC_TRUSTED_INPUT;
        Crypto.random.generateData(buffer, offset, (short)3);
        offset += 3;
        Crypto.digestFull.doFinal(scratch256, (short)0, (short)0, scratch256, (short)0);
        Crypto.digestFull.doFinal(scratch256, (short)0, (short)32, buffer, offset);
        offset += 32;
        GenericBEHelper.swap(TC.SIZEOF_U32, buffer, offset, TC.ctx, TC.TX_I_TRANSACTION_TARGET_INPUT);
        offset += 4;
        Util.arrayCopyNonAtomic(TC.ctx, TC.TX_A_TRANSACTION_AMOUNT, buffer, offset, TC.SIZEOF_AMOUNT);
        offset += TC.SIZEOF_AMOUNT;
        Crypto.initCipher(trustedInputKey, true);
        Crypto.blobEncryptDecrypt.doFinal(buffer, (short)0, offset, scratch256, (short)0);
        Util.arrayCopyNonAtomic(scratch256, (short)(offset - 8), buffer, offset, (short)8);
        offset += 8;
        apdu.setOutgoingAndSend((short)0, offset);
    }
}
 
Example 20
Source File: GidsApplet.java    From GidsApplet with GNU General Public License v3.0 4 votes vote down vote up
/**
 * \brief Compute a digital signature of the data from the apdu
 * 			using the private key referenced by	an earlier
 *			MANAGE SECURITY ENVIRONMENT apdu.
 *
 * \attention The apdu should contain a hash, not raw data for RSA keys.
 * 				PKCS1 padding will be applied if neccessary.
 *
 * \param apdu The PERFORM SECURITY OPERATION apdu with P1=9E and P2=9A.
 *
 * \throw ISOException SW_CONDITIONS_NOT_SATISFIED, SW_WRONG_LENGTH
 * 						and SW_UNKNOWN.
 */
private void computeDigitalSignature(APDU apdu) throws ISOException {
    byte[] buf = apdu.getBuffer();
    short lc, le;
    short sigLen = 0;
    PrivateKey rsaKey = null;
    byte[] ram_buf = transmitManager.GetRamBuffer();
    CRTKeyFile key = (CRTKeyFile) currentKey[0];

    switch((byte) (currentAlgorithmRef[0] & 0xF0)) {
    case (byte) 0x10:
        // padding made off card -> raw encryption to be performed
        lc = transmitManager.doChainingOrExtAPDU(apdu);

        // RSA signature operation.
        rsaKey = key.GetKey().getPrivate();

        rsaRawCipher.init(rsaKey, Cipher.MODE_ENCRYPT);
        sigLen = rsaRawCipher.doFinal(ram_buf, (short) 0, lc, ram_buf, (short)0);

        transmitManager.sendDataFromRamBuffer(apdu, (short)0, sigLen);
        break;
    case (byte) 0x50:
        // rsa padding made by the card, only the hash is provided

        // Receive.
        // Bytes received must be Lc.
        lc = apdu.setIncomingAndReceive();

        // RSA signature operation.
        rsaKey = key.GetKey().getPrivate();

        if(lc > (short) 247) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
        
        rsaPkcs1Cipher.init(rsaKey, Cipher.MODE_ENCRYPT);
        sigLen = rsaPkcs1Cipher.doFinal(buf, ISO7816.OFFSET_CDATA, lc, ram_buf, (short)0);

        /*if(sigLen != 256) {
            ISOException.throwIt(ISO7816.SW_UNKNOWN);
        }*/

        transmitManager.sendDataFromRamBuffer(apdu, (short)0, sigLen);
        break;

    default:
        // Wrong/unknown algorithm.
        ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }
}