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

The following examples show how to use javacard.framework.APDU#sendBytesLong() . 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: NdefApplet.java    From openjavacard-ndef with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Process a READ BINARY command
 *
 * This supports simple reads at any offset.
 *
 * The length of the returned data is limited
 * by the maximum R-APDU length as well as by
 * the maximum read size NDEF_MAX_READ.
 *
 * @param apdu to process
 * @throws ISOException on error
 */
private void processReadBinary(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();

    // access the file
    byte[] file = accessFileForRead(vars[VAR_SELECTED_FILE]);

    // get and check the read offset
    short offset = Util.getShort(buffer, ISO7816.OFFSET_P1);
    if(offset < 0 || offset >= file.length) {
        ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
    }

    // determine the output size
    short le = apdu.setOutgoingNoChaining();
    if(le > NDEF_MAX_READ) {
        le = NDEF_MAX_READ;
    }

    // adjust for end of file
    short limit = (short)(offset + le);
    if(limit < 0) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    if(limit >= file.length) {
        le = (short)(file.length - offset);
    }

    // send the requested data
    apdu.setOutgoingLength(le);
    apdu.sendBytesLong(file, offset, le);
}
 
Example 2
Source File: NdefApplet.java    From openjavacard-ndef with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Process a READ BINARY command
 *
 * This supports simple reads at any offset.
 *
 * The length of the returned data is limited
 * by the maximum R-APDU length as well as by
 * the maximum read size NDEF_MAX_READ.
 *
 * @param apdu to process
 * @throws ISOException on error
 */
private void processReadBinary(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();

    // access the file
    byte[] file = accessFileForRead(vars[VAR_SELECTED_FILE]);

    // get and check the read offset
    short offset = Util.getShort(buffer, ISO7816.OFFSET_P1);
    if(offset < 0 || offset >= file.length) {
        ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
    }

    // determine the output size
    short le = apdu.setOutgoingNoChaining();
    if(le > NDEF_MAX_READ) {
        le = NDEF_MAX_READ;
    }

    // adjust for end of file
    short limit = (short)(offset + le);
    if(limit < 0) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    if(limit >= file.length) {
        le = (short)(file.length - offset);
    }

    // send the requested data
    apdu.setOutgoingLength(le);
    apdu.sendBytesLong(file, offset, le);
}
 
Example 3
Source File: IsoApplet.java    From IsoApplet with GNU General Public License v3.0 5 votes vote down vote up
/**
 * \brief Send the data from ram_buf, using either extended APDUs or GET RESPONSE.
 *
 * \param apdu The APDU object, in STATE_OUTGOING state.
 *
 * \param pos The position in ram_buf at where the data begins
 *
 * \param len The length of the data to be sent. If zero, 9000 will be
 *            returned
 */
private void sendLargeData(APDU apdu, short pos, short len) {
    if(len <= 0) {
        ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_BYTES_REMAINING] = 0;
        ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] = 0;
        ISOException.throwIt(ISO7816.SW_NO_ERROR);
    }

    if((short)(pos + len) > RAM_BUF_SIZE) {
        ISOException.throwIt(ISO7816.SW_UNKNOWN);
    }

    if(DEF_EXT_APDU) {
        apdu.setOutgoingLength(len);
        apdu.sendBytesLong(ram_buf, pos, len);
    } else {
        // We have 256 Bytes send-capacity per APDU.
        // Send directly from ram_buf, then prepare for chaining.
        short sendLen = len > 256 ? 256 : len;
        apdu.setOutgoingLength(sendLen);
        apdu.sendBytesLong(ram_buf, pos, sendLen);
        short bytesLeft = (short)(len - sendLen);
        if(bytesLeft > 0) {
            ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_BYTES_REMAINING] = bytesLeft;
            ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] = (short)(pos + sendLen);
            short getRespLen = bytesLeft > 256 ? 256 : bytesLeft;
            ISOException.throwIt( (short)(ISO7816.SW_BYTES_REMAINING_00 | getRespLen) );
            // The next part of the data is now in ram_buf, metadata is in ram_chaining_cache.
            // It can be fetched by the host via GET RESPONSE.
        } else {
            ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_BYTES_REMAINING] = 0;
            ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] = 0;
            ISOException.throwIt(ISO7816.SW_NO_ERROR);
        }
    }
}
 
Example 4
Source File: TransmitManager.java    From GidsApplet with GNU General Public License v3.0 4 votes vote down vote up
/**
 * \brief Send the data from ram_buf, using either extended APDUs or GET RESPONSE.
 *
 * \param apdu The APDU object, in STATE_OUTGOING state.
 *
 * \param pos The position in ram_buf at where the data begins
 *
 * \param len The length of the data to be sent. If zero, 9000 will be
 *            returned
 */
private void sendData(APDU apdu) {
    short le;
    short remaininglen = 0;
    byte data[] = null;
    short pos = chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS];

    le = apdu.setOutgoing();
    // le has not been set
    if(le == 0) {
        // we get here when called from the Shared VMWare reader
        byte ins = apdu.getBuffer()[ISO7816.OFFSET_INS];
        if ( ins != GidsApplet.INS_GENERATE_ASYMMETRIC_KEYPAIR) {
            le = 256;
        } else {
            le = 0;
        }
    }

    if (chaining_object[CHAINING_OBJECT] == null) {
        data = ram_buf;
        remaininglen = chaining_cache[RAM_CHAINING_CACHE_OFFSET_BYTES_REMAINING];
    } else if (chaining_object[CHAINING_OBJECT] instanceof Record) {
        Record record = (Record) (chaining_object[CHAINING_OBJECT]);
        data = record.GetData();
        remaininglen = (short) (((short) data.length) - pos);
    } else if (chaining_object[CHAINING_OBJECT] instanceof Record[]) {
        data = ram_buf;
        remaininglen = copyRecordsToRamBuf(le);
        pos = 0;
    }

    // We have 256 Bytes send-capacity per APDU.
    short sendLen = remaininglen > le ? le : remaininglen;
    apdu.setOutgoingLength(sendLen);
    apdu.sendBytesLong(data, pos, sendLen);
    // the position when using Record[] is maintened by copyRecordsToRamBuf
    if (chaining_object[CHAINING_OBJECT] == null || !(chaining_object[CHAINING_OBJECT] instanceof Record[])) {
        chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS]+= sendLen;
    }

    if (chaining_object[CHAINING_OBJECT] == null) {
        chaining_cache[RAM_CHAINING_CACHE_OFFSET_BYTES_REMAINING] -= sendLen;
    }
    remaininglen -= sendLen;
    if(remaininglen > 0) {
        short nextRespLen = remaininglen > 256 ? 256 : remaininglen;
        ISOException.throwIt( (short)(ISO7816.SW_BYTES_REMAINING_00 | nextRespLen) );
    } else {
        Clear(true);
        return;
    }
}
 
Example 5
Source File: NdefApplet.java    From openjavacard-ndef with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Process a READ BINARY command
 *
 * This supports simple reads at any offset.
 *
 * The length of the returned data is limited
 * by the maximum R-APDU length as well as by
 * the maximum read size NDEF_MAX_READ.
 *
 * @param apdu to process
 * @throws ISOException on error
 */
private void processReadBinary(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();

    // access the file
    byte[] file = accessFileForRead(vars[VAR_SELECTED_FILE]);

    // get and check the read offset
    short offset = Util.getShort(buffer, ISO7816.OFFSET_P1);
    if(offset < 0 || offset >= file.length) {
        ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
    }

    // determine the output size
    short le = apdu.setOutgoingNoChaining();
    if(le > NDEF_MAX_READ) {
        le = NDEF_MAX_READ;
    }

    // adjust for end of file
    short limit = (short)(offset + le);
    if(limit < 0) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    if(limit >= file.length) {
        le = (short)(file.length - offset);
    }

    // send the requested data
    if(vars[VAR_SELECTED_FILE] == FILEID_NDEF_CAPABILITIES) {
        // send fixed capabilities
        Util.arrayCopyNonAtomic(file, (short)0,
                                buffer, (short)0,
                                (short)file.length);
        fixCaps(buffer, (short)0, (short)file.length);
        apdu.setOutgoingLength(le);
        apdu.sendBytesLong(buffer, offset, le);
    } else {
        // send directly
        apdu.setOutgoingLength(le);
        apdu.sendBytesLong(file, offset, le);
    }
}
 
Example 6
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);
    }
}