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

The following examples show how to use javacard.framework.APDU#getOffsetCdata() . 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: 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 2
Source File: IsoApplet.java    From IsoApplet with GNU General Public License v3.0 5 votes vote down vote up
/**
 * \brief Receive the data sent by chaining or extended apdus and store it in ram_buf.
 *
 * This is a convienience method if large data has to be accumulated using command chaining
 * or extended apdus. The apdu must be in the INITIAL state, i.e. setIncomingAndReceive()
 * might not have been called already.
 *
 * \param apdu The apdu object in the initial state.
 *
 * \throw ISOException SW_WRONG_LENGTH
 */
private short doChainingOrExtAPDU(APDU apdu) throws ISOException {
    byte[] buf = apdu.getBuffer();
    short recvLen = apdu.setIncomingAndReceive();
    short offset_cdata = apdu.getOffsetCdata();

    // Receive data (short or extended).
    while (recvLen > 0) {
        if((short)(ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] + recvLen) > RAM_BUF_SIZE) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
        Util.arrayCopyNonAtomic(buf, offset_cdata, ram_buf, ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS], recvLen);
        ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] += recvLen;
        recvLen = apdu.receiveBytes(offset_cdata);
    }

    if(isCommandChainingCLA(apdu)) {
        // We are still in the middle of a chain, otherwise there would not have been a chaining CLA.
        // Make sure the caller does not forget to return as the data should only be interpreted
        // when the chain is completed (when using this method).
        ISOException.throwIt(ISO7816.SW_NO_ERROR);
        return (short)0;
    } else {
        // Chain has ended or no chaining.
        // We did receive the data, everything is fine.
        // Reset the current position in ram_buf.
        recvLen = (short) (recvLen + ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS]);
        ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] = 0;
        return recvLen;
    }
}
 
Example 3
Source File: U2FApplet.java    From CCU2F with Apache License 2.0 4 votes vote down vote up
private void handleSign(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    short len = apdu.setIncomingAndReceive();
    short dataOffset = apdu.getOffsetCdata();
    byte p1 = buffer[ISO7816.OFFSET_P1];
    boolean sign = false;
    boolean counterOverflow = true;
    short keyHandleLength;
    boolean extendedLength = (dataOffset != ISO7816.OFFSET_CDATA);
    short outOffset = SCRATCH_PAD;
    if (len < 65) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    switch(p1) {
    case P1_SIGN_OPERATION:
        sign = true;
        break;
    case P1_SIGN_CHECK_ONLY:
        break;
    default:
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }
    // Check if the counter overflowed
    if (counterOverflowed) {
        ISOException.throwIt(ISO7816.SW_FILE_FULL);
    }
    // Verify key handle
    if (localPrivateTransient) {
        Secp256r1.setCommonCurveParameters(localPrivateKey);
    }
    keyHandleLength = (short)(buffer[(short)(dataOffset + 64)] & 0xff);
    if (!fidoImpl.unwrap(buffer, (short)(dataOffset + 65), keyHandleLength, buffer, (short)(dataOffset + APDU_APPLICATION_PARAMETER_OFFSET), (sign ? localPrivateKey : null))) {
        ISOException.throwIt(FIDO_SW_INVALID_KEY_HANDLE);
    }
    // If not signing, return with the "correct" exception
    if (!sign) {
        ISOException.throwIt(FIDO_SW_TEST_OF_PRESENCE_REQUIRED);
    }
    // If signing, only proceed if user presence can be validated
    if ((flags & INSTALL_FLAG_DISABLE_USER_PRESENCE) == 0) {
        if (scratchPersistent[0] != 0) {
            ISOException.throwIt(FIDO_SW_TEST_OF_PRESENCE_REQUIRED);
        }
    }
    scratchPersistent[0] = (byte)1;
    // Increase the counter
    boolean carry = false;
    JCSystem.beginTransaction();
    for (byte i=0; i<4; i++) {
        short addValue = (i == 0 ? (short)1 : (short)0);
        short val = (short)((short)(counter[(short)(4 - 1 - i)] & 0xff) + addValue);
        if (carry) {
            val++;
        }
        carry = (val > 255);
        counter[(short)(4 - 1 - i)] = (byte)val;
    }
    JCSystem.commitTransaction();
    if (carry) {
        // Game over
        counterOverflowed = true;
        ISOException.throwIt(ISO7816.SW_FILE_FULL);
    }
    // Prepare reply
    scratch[outOffset++] = FLAG_USER_PRESENCE_VERIFIED;
    outOffset = Util.arrayCopyNonAtomic(counter, (short)0, scratch, outOffset, (short)4);
    localSignature.init(localPrivateKey, Signature.MODE_SIGN);
    localSignature.update(buffer, (short)(dataOffset + APDU_APPLICATION_PARAMETER_OFFSET), (short)32);
    localSignature.update(scratch, SCRATCH_PAD, (short)5);
    outOffset += localSignature.sign(buffer, (short)(dataOffset + APDU_CHALLENGE_OFFSET), (short)32, scratch, outOffset);
  
    if (extendedLength) {
        // If using extended length, the message can be completed and sent immediately
        scratch[SCRATCH_TRANSPORT_STATE] = TRANSPORT_EXTENDED;
        Util.arrayCopyNonAtomic(scratch, SCRATCH_PAD, buffer, (short)0, outOffset);
        apdu.setOutgoingAndSend((short)0, (short)(outOffset - SCRATCH_PAD));
    }
    else {
        // Otherwise send the first chunk
        scratch[SCRATCH_TRANSPORT_STATE] = TRANSPORT_NOT_EXTENDED;
        Util.setShort(scratch, SCRATCH_CURRENT_OFFSET, (short)0);
        Util.setShort(scratch, SCRATCH_SIGNATURE_LENGTH, (short)0);
        Util.setShort(scratch, SCRATCH_NONCERT_LENGTH, (short)(outOffset - SCRATCH_PAD));
        Util.setShort(scratch, SCRATCH_FULL_LENGTH, (short)(outOffset - SCRATCH_PAD));
        scratch[SCRATCH_INCLUDE_CERT] = (byte)0;
        handleGetData(apdu);
    }
}
 
Example 4
Source File: ECTesterAppletExtended.java    From ECTester with MIT License 4 votes vote down vote up
short getOffsetCdata(APDU apdu) {
    return apdu.getOffsetCdata();
}
 
Example 5
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 6
Source File: IsoApplet.java    From IsoApplet with GNU General Public License v3.0 4 votes vote down vote up
/**
 * \brief Process the RESET RETRY COUNTER apdu (INS = 2C).
 *
 * This is used to unblock the PIN with the PUK and set a new PIN value.
 *
 * \param apdu The RESET RETRY COUNTER apdu.
 *
 * \throw ISOException SW_COMMAND_NOT_ALLOWED, ISO7816.SW_WRONG_LENGTH, SW_INCORRECT_P1P2,
 *			SW_PIN_TRIES_REMAINING.
 */
public void	processResetRetryCounter(APDU apdu) throws ISOException {
    byte[] buf = apdu.getBuffer();
    byte p1 = buf[ISO7816.OFFSET_P1];
    byte p2 = buf[ISO7816.OFFSET_P2];
    short lc;
    short offset_cdata;

    if(state != STATE_OPERATIONAL_ACTIVATED) {
        ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
    }

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

    // Length of data field.
    if(lc < (short)(PUK_LENGTH + PIN_MIN_LENGTH)
            || lc > (short)(PUK_LENGTH + PIN_MAX_LENGTH)) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // We expect the PUK followed by a new PIN.
    if(p1 != (byte) 0x00 || p2 != (byte) 0x01) {
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }

    // Check the PUK.
    if(puk == null) {
        ISOException.throwIt(SW_PIN_TRIES_REMAINING);
    } else if (!puk.check(buf, offset_cdata, PUK_LENGTH)) {
        ISOException.throwIt((short)(SW_PIN_TRIES_REMAINING | puk.getTriesRemaining()));
    } else {
        // If we're here, the PUK was correct.
        // Pad the new PIN, if not done by caller. We don't want any gargabe from the APDU buffer to be part of the new PIN.
        Util.arrayFillNonAtomic(buf, (short)(offset_cdata + lc), (short)(PUK_LENGTH + PIN_MAX_LENGTH - lc), (byte) 0x00);

        // Set the PIN.
        pin.update(buf, (short)(offset_cdata+PUK_LENGTH), PIN_MAX_LENGTH);
        pin.resetAndUnblock();
    }
}
 
Example 7
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);
    }
}