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

The following examples show how to use javacard.framework.APDU#setOutgoingAndSend() . 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: 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 2
Source File: OCUnitTests.java    From JCMathLib with MIT License 6 votes vote down vote up
void test_EC_MUL(APDU apdu) {
    byte[] apdubuf = apdu.getBuffer();
    short p1_len = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);

    PM.check(PM.TRAP_EC_MUL_1);
    Bignat scalar = m_testBN1;
    scalar.set_size(p1_len);
    scalar.from_byte_array(p1_len, (short) 0, apdubuf, ISO7816.OFFSET_CDATA);
    PM.check(PM.TRAP_EC_MUL_2);
    m_testPoint1.setW(apdubuf, (short) (ISO7816.OFFSET_CDATA + p1_len), m_testCurve.POINT_SIZE);
    PM.check(PM.TRAP_EC_MUL_3);
    m_testPoint1.multiplication(scalar);
    PM.check(PM.TRAP_EC_MUL_4);

    short len = m_testPoint1.getW(apdubuf, (short) 0);
    PM.check(PM.TRAP_EC_MUL_5);
    apdu.setOutgoingAndSend((short) 0, len);
}
 
Example 3
Source File: OCUnitTests.java    From JCMathLib with MIT License 6 votes vote down vote up
void test_BN_EXP_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_EXP_MOD_1);    
    Bignat num1 = m_testBN1;
    num1.set_size(p1);
    PM.check(PM.TRAP_BN_EXP_MOD_2);
    Bignat num2 = m_testBN2;
    num2.set_size(p2);
    PM.check(PM.TRAP_BN_EXP_MOD_3);
    Bignat mod = m_testBN3;
    mod.set_size((short) (dataLen - p1 - p2));
    PM.check(PM.TRAP_BN_EXP_MOD_4);
    num1.from_byte_array(p1, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
    num2.from_byte_array(p2, (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
    mod.from_byte_array((short)(dataLen-p1-p2), (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1+p2));
    PM.check(PM.TRAP_BN_EXP_MOD_5);
    num1.mod_exp(num2, mod);
    PM.check(PM.TRAP_BN_EXP_MOD_6);
    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 vote down vote up
void test_BN_SUB_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_SUB_MOD_1);    
    Bignat num1 = m_testBN1;
    num1.set_size(p1);
    PM.check(PM.TRAP_BN_SUB_MOD_2);
    Bignat num2 = m_testBN2;
    num2.set_size(p2);
    PM.check(PM.TRAP_BN_SUB_MOD_3);
    Bignat mod = m_testBN3;
    mod.set_size((short) (dataLen - p1 - p2));
    PM.check(PM.TRAP_BN_SUB_MOD_4);
    num1.from_byte_array(p1, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
    num2.from_byte_array(p2, (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
    mod.from_byte_array((short)(dataLen-p1-p2), (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1+p2));
    PM.check(PM.TRAP_BN_SUB_MOD_5);
    num1.mod_sub(num2, mod);
    PM.check(PM.TRAP_BN_SUB_MOD_6);
    short len = num1.copy_to_buffer(apdubuf, (short) 0);
    apdu.setOutgoingAndSend((short) 0, len);
}
 
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 handleGetFeatures(APDU apdu) throws ISOException {
 byte[] buffer = apdu.getBuffer();
 buffer[0] = (byte)0;
 if (proprietaryAPI != null) {
  buffer[0] |= JC_FEATURE_HAS_PROPRIETARY_API;
 }
 apdu.setOutgoingAndSend((short)0, (short)1);
}
 
Example 6
Source File: OCUnitTests.java    From JCMathLib with MIT License 5 votes vote down vote up
void test_EC_GEN(APDU apdu) {
    byte[] apdubuf = apdu.getBuffer();

    PM.check(PM.TRAP_EC_GEN_1);
    m_testPoint1.randomize();
    PM.check(PM.TRAP_EC_GEN_2);

    short len = m_testPoint1.getW(apdubuf, (short) 0);
    PM.check(PM.TRAP_EC_GEN_3);
    apdu.setOutgoingAndSend((short) 0, len);
}
 
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 handleGetContactlessLimit(APDU apdu) throws ISOException {
    if ((setup == TC.FALSE) || (setup != TC.TRUE)) {
        ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }
    Util.arrayCopyNonAtomic(limits, (short)0, scratch256, (short)0, LIMIT_LAST);
    apdu.setOutgoingAndSend((short)0, LIMIT_LAST);
}
 
Example 8
Source File: OCUnitTests.java    From JCMathLib with MIT License 5 votes vote down vote up
void test_BN_SQRT(APDU apdu, short dataLen) {
    byte[] apdubuf = apdu.getBuffer();
    short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);

    Bignat num = m_testBN1;
    num.set_size(p1);
    num.from_byte_array(p1, p1, apdubuf, ISO7816.OFFSET_CDATA);
    Bignat num2 = m_testBN2;
    num2.clone(m_testCurve.pBN);
    num.sqrt_FP(num2);
    short len = num.copy_to_buffer(apdubuf, (short) 0);
    apdu.setOutgoingAndSend((short) 0, len);
}
 
Example 9
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 10
Source File: PasswordManagerApplet.java    From sim-password-manager with Apache License 2.0 4 votes vote down vote up
private void encrypt(APDU apdu) {
    if (!keysGenerated) {
        ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }

    byte[] buff = apdu.getBuffer();
    short len = apdu.setIncomingAndReceive();

    if (len > MAX_DATA_LEN) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    prng(iv, OFFSET_ZERO, AES_BLOCK_LEN);
    initAes();

    try {
        aesCipher.RoundKeysSchedule(keyBytes, (short) 0, roundKeysBuff);

        short offset = Util.arrayCopyNonAtomic(buff, ISO7816.OFFSET_CDATA,
                cipherBuff, OFFSET_ZERO, len);
        short padSize = addPadding(cipherBuff, offset, len);
        short paddedLen = (short) (len + padSize);
        short blocks = (short) (paddedLen / AES_BLOCK_LEN);

        for (short i = 0; i < blocks; i++) {
            short cipherOffset = (short) (i * AES_BLOCK_LEN);
            for (short j = 0; j < AES_BLOCK_LEN; j++) {
                cbcV[j] ^= cipherBuff[(short) (cipherOffset + j)];
            }

            // encrypts in place
            boolean success = aesCipher.AESEncryptBlock(cbcV, OFFSET_ZERO,
                    roundKeysBuff);
            if (!success) {
                ISOException.throwIt(ISO7816.SW_DATA_INVALID);
            }
            Util.arrayCopyNonAtomic(cbcV, OFFSET_ZERO, cipherBuff,
                    cipherOffset, AES_BLOCK_LEN);
        }

        offset = Util.arrayCopyNonAtomic(iv, OFFSET_ZERO, buff,
                OFFSET_ZERO, AES_BLOCK_LEN);
        offset = Util.arrayCopyNonAtomic(cipherBuff, OFFSET_ZERO, buff,
                AES_BLOCK_LEN, paddedLen);
        apdu.setOutgoingAndSend(OFFSET_ZERO,
                (short) (AES_BLOCK_LEN + paddedLen));
    } finally {
        clearCipherState();
    }
}
 
Example 11
Source File: U2FApplet.java    From CCU2F with Apache License 2.0 4 votes vote down vote up
public void process(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    if (selectingApplet()) {
        if (attestationCertificateSet) {
            Util.arrayCopyNonAtomic(VERSION, (short)0, buffer, (short)0, (short)VERSION.length);
            apdu.setOutgoingAndSend((short)0, (short)VERSION.length);
        }
        return;
    }
    if (buffer[ISO7816.OFFSET_CLA] == PROPRIETARY_CLA) {
        if (attestationCertificateSet) {
            ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
        }
        switch(buffer[ISO7816.OFFSET_INS]) {
        case FIDO_ADM_SET_ATTESTATION_CERT:
            handleSetAttestationCert(apdu);
            break;
        default:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }
    else if (buffer[ISO7816.OFFSET_CLA] == FIDO_CLA) {
        if (!attestationCertificateSet) {
            ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
        }
        switch(buffer[ISO7816.OFFSET_INS]) {
        case FIDO_INS_ENROLL:
            handleEnroll(apdu);
            break;
        case FIDO_INS_SIGN:
            handleSign(apdu);
            break;
        case FIDO_INS_VERSION:
            handleVersion(apdu);
            break;
        case ISO_INS_GET_DATA:
            handleGetData(apdu);
            break;
        default:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }
    else {
        ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
    }
}
 
Example 12
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 13
Source File: GidsApplet.java    From GidsApplet with GNU General Public License v3.0 4 votes vote down vote up
/**
 * \brief Decipher the data from the apdu using the private key referenced by
 * 			an earlier MANAGE SECURITY ENVIRONMENT apdu.
 *
 * \param apdu The PERFORM SECURITY OPERATION apdu with P1=80 and P2=86.
 *
 * \throw ISOException SW_CONDITIONS_NOT_SATISFIED, SW_WRONG_LENGTH and
 *						SW_WRONG_DATA
 */
private void decipher(APDU apdu) {
    byte[] buf = apdu.getBuffer();
    short offset_cdata;
    short lc;
    short decLen = -1;
    byte[] ram_buf = transmitManager.GetRamBuffer();
    Cipher cipher = null;

    lc = transmitManager.doChainingOrExtAPDU(apdu);
    offset_cdata = 0;

    // Padding indicator should be "No further indication".
    if(buf[offset_cdata] != (byte) 0x00) {
        ISOException.throwIt(ISO7816.SW_WRONG_DATA);
    }

    switch((byte) (currentAlgorithmRef[0] & 0xF0)) {

    case (byte) 0x80:
        cipher = rsaOaepCipher;
        break;
    case (byte) 0x40:
        cipher = rsaPkcs1Cipher;
        break;
    case (byte) 0x00:
        cipher = rsaRawCipher;
        break;
    default:
        ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
    }
    // Get the key - it must be an RSA private key,
    // checks have been done in MANAGE SECURITY ENVIRONMENT.
    CRTKeyFile key = (CRTKeyFile) currentKey[0];
    PrivateKey theKey = key.GetKey().getPrivate();

    // Check the length of the cipher.
    // Note: The first byte of the data field is the padding indicator
    //		 and therefor not part of the ciphertext.
    if(lc !=  (short)(theKey.getSize() / 8)) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    cipher.init(theKey, Cipher.MODE_DECRYPT);

    try {
        decLen = cipher.doFinal(ram_buf, (short) 0, lc,
                                buf, (short) 0);
    } catch(CryptoException e) {
        ISOException.throwIt(ISO7816.SW_WRONG_DATA);
    }

    // We have to send at most 256 bytes. A short APDU can handle that - only one send operation neccessary.
    apdu.setOutgoingAndSend((short)0, decLen);
}
 
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 handleSignMessage(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    short offset = ISO7816.OFFSET_CDATA;
    if (buffer[ISO7816.OFFSET_P1] == P1_PREPARE_MESSAGE) {
        byte derivationSize = buffer[offset++];
        boolean addressVerified = false;
        if (Util.arrayCompare(buffer, offset, SLIP13_HEAD, (short)0, (short)SLIP13_HEAD.length) == (short)0) {
            addressVerified = true;
        }
        else {
            for (byte i=0; i<derivationSize; i++) {
                if ((Util.arrayCompare(buffer, (short)(offset + 2), BITID_DERIVE, (short)0, (short)BITID_DERIVE.length) == (short)0) ||
                    (Util.arrayCompare(buffer, (short)(offset + 2), BITID_DERIVE_MULTIPLE, (short)0, (short)BITID_DERIVE_MULTIPLE.length) == (short)0)) {
                    addressVerified = true;
                    break;
                }
                offset += 4;
            }
        }
        if (!addressVerified) {
            ISOException.throwIt(ISO7816.SW_WRONG_DATA);
        }
        offset = (short)(ISO7816.OFFSET_CDATA + 1 + 4 * derivationSize);
        short messageLength = (short)(buffer[offset++] & 0xff);
        Crypto.digestFull.reset();
        Crypto.digestFull.update(SIGNMAGIC, (short)0, (short)SIGNMAGIC.length);
        scratch256[(short)100] = (byte)messageLength;
        Crypto.digestFull.update(scratch256, (short)100, (short)1);
        Crypto.digestFull.doFinal(buffer, offset, messageLength, scratch256, (short)32);
        signTransientPrivate(scratch256, (short)0, scratch256, (short)32, scratch256, (short)100);
        Util.arrayFillNonAtomic(scratch256, (short)0, (short)64, (byte)0x00);
        buffer[(short)0] = (byte)0x00;
        TC.ctx[TC.TX_B_MESSAGE_SIGN_READY] = (byte)0x01;
        apdu.setOutgoingAndSend((short)0, (short)1);
    }
    else
    if (buffer[ISO7816.OFFSET_P1] == P1_SIGN_MESSAGE) {
        if (TC.ctx[TC.TX_B_MESSAGE_SIGN_READY] != (byte)0x01) {
            ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
        }
        TC.ctx[TC.TX_B_MESSAGE_SIGN_READY] = (byte)0x00;
        short signatureSize = (short)((short)(scratch256[(short)101] & 0xff) + 2);
        Util.arrayCopyNonAtomic(scratch256, (short)100, buffer, (short)0, signatureSize);
        apdu.setOutgoingAndSend((short)0, signatureSize);
    }
    else {
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }
}
 
Example 15
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 16
Source File: IsoApplet.java    From IsoApplet with GNU General Public License v3.0 4 votes vote down vote up
/**
 * \brief Decipher the data from the apdu using the private key referenced by
 * 			an earlier MANAGE SECURITY ENVIRONMENT apdu.
 *
 * \param apdu The PERFORM SECURITY OPERATION apdu with P1=80 and P2=86.
 *
 * \throw ISOException SW_CONDITIONS_NOT_SATISFIED, SW_WRONG_LENGTH and
 *						SW_WRONG_DATA
 */
private void decipher(APDU apdu) {
    short offset_cdata;
    short lc;
    short decLen = -1;

    lc = doChainingOrExtAPDU(apdu);
    offset_cdata = 0;

    // Padding indicator should be "No further indication".
    if(ram_buf[offset_cdata] != (byte) 0x00) {
        ISOException.throwIt(ISO7816.SW_WRONG_DATA);
    }

    switch(currentAlgorithmRef[0]) {

    case ALG_RSA_PAD_PKCS1:
        // Get the key - it must be an RSA private key,
        // checks have been done in MANAGE SECURITY ENVIRONMENT.
        RSAPrivateCrtKey theKey = (RSAPrivateCrtKey) keys[currentPrivateKeyRef[0]];

        // Check the length of the cipher.
        // Note: The first byte of the data field is the padding indicator
        //		 and therefor not part of the ciphertext.
        if((short)(lc-1) !=  (short)(theKey.getSize() / 8)) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }

        rsaPkcs1Cipher.init(theKey, Cipher.MODE_DECRYPT);
        try {
            decLen = rsaPkcs1Cipher.doFinal(ram_buf, (short)(offset_cdata+1), (short)(lc-1),
                                            apdu.getBuffer(), (short) 0);
        } catch(CryptoException e) {
            ISOException.throwIt(ISO7816.SW_WRONG_DATA);
        }

        // We have to send at most 256 bytes. A short APDU can handle that - only one send operation neccessary.
        apdu.setOutgoingAndSend((short)0, decLen);
        break;

    default:
        ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
    }
}
 
Example 17
Source File: U2FApplet.java    From CCU2F with Apache License 2.0 4 votes vote down vote up
private void handleVersion(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    Util.arrayCopyNonAtomic(VERSION, (short)0, buffer, (short)0, (short)VERSION.length);
    apdu.setOutgoingAndSend((short)0, (short)VERSION.length);
}
 
Example 18
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 19
Source File: TransitApplet.java    From JCMathLib with MIT License 4 votes vote down vote up
/**
 * 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 20
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
private static void handleGetFirmwareVersion(APDU apdu) throws ISOException {
 byte[] buffer = apdu.getBuffer();
 Util.arrayCopyNonAtomic(FIRMWARE_VERSION, (short)0, buffer, (short)0, (short)FIRMWARE_VERSION.length);
 apdu.setOutgoingAndSend((short)0, (short)FIRMWARE_VERSION.length);
}