Java Code Examples for javacard.framework.JCSystem#beginTransaction()

The following examples show how to use javacard.framework.JCSystem#beginTransaction() . 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: PasswordManagerApplet.java    From sim-password-manager with Apache License 2.0 5 votes vote down vote up
private void generateKeys(APDU apdu) {
    if (keysGenerated) {
        ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }

    try {
        JCSystem.beginTransaction();
        prng(keyBytes, OFFSET_ZERO, KEY_LENGTH);
        keysGenerated = true;
    } finally {
        JCSystem.commitTransaction();
    }
}
 
Example 3
Source File: PasswordManagerApplet.java    From sim-password-manager with Apache License 2.0 5 votes vote down vote up
private void clear(APDU apdu) {
    try {
        JCSystem.beginTransaction();
        for (short i = 0; i < KEY_LENGTH; i++) {
            keyBytes[i] = 0;
        }

        keysGenerated = false;
        prngCounter = 0;
    } finally {
        JCSystem.commitTransaction();
    }
}
 
Example 4
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 5 votes vote down vote up
private void computeSignature(APDU apdu) {
  byte[] buffer = apdu.getBuffer();
  short length = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
  // Make sure that DigestInfo is <= 40% of the RSA key length.
  if ((short) (length * 4) > (short) (RSA_KEY_LENGTH_BYTES * 10) ||
      apdu.setIncomingAndReceive() != length) {
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  }
  if (!pinSubmitted[PIN_INDEX_PW1] || !pins[PIN_INDEX_PW1].isValidated()) {
    ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
  }
  if (!signatureKey.getPrivate().isInitialized()) {
    ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
  }
  if (pinValidForMultipleSignatures == (byte) 0) {
    pinSubmitted[PIN_INDEX_PW1] = false;
  }

  cipherRSA.init(signatureKey.getPrivate(), Cipher.MODE_ENCRYPT);
  cipherRSA.doFinal(buffer, ISO7816.OFFSET_CDATA, length, buffer, (short) 0);
  JCSystem.beginTransaction();
  if (signatureCounter[2] != (byte) 0xFF) {
    signatureCounter[2] = (byte) ((signatureCounter[2] & 0xFF) + 1);
  } else {
    signatureCounter[2] = 0;
    if (signatureCounter[1] != (byte) 0xFF) {
      signatureCounter[1] = (byte) ((signatureCounter[1] & 0xFF) + 1);
    } else if (signatureCounter[0] != (byte) 0xFF) {
      signatureCounter[1] = 0;
      signatureCounter[0] = (byte) ((signatureCounter[0] & 0xFF) + 1);
    } else {
      JCSystem.abortTransaction();
      ISOException.throwIt(ISO7816.SW_FILE_FULL);
    }
  }
  JCSystem.commitTransaction();
  apdu.setOutgoingAndSend((short) 0, RSA_KEY_LENGTH_BYTES);
}
 
Example 5
Source File: TransitApplet.java    From JCMathLib with MIT License 4 votes vote down vote up
/**
 * Processes a transit entry event. The passed-in entry station ID is
 * recorded and the correlation ID is incremented. The UID and the
 * correlation ID are returned in the response message.
 * 
 * Request Message: [2-bytes Entry Station ID]
 * 
 * Response Message: [[2-bytes UID], [2-bytes Correlation ID]]
 * 
 * @param buffer
 *            The APDU buffer
 * @param messageOffset
 *            The offset of the request message content in the APDU buffer
 * @param messageLength
 *            The length of the request message content.
 * @return The offset at which content can be appended to the response
 *         message
 */
private short processEntry(byte[] buffer, short messageOffset,
        short messageLength) {

    // Request Message: [2-bytes Entry Station ID]

    if (messageLength != 2) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // Check minimum balance
    if (balance < MIN_TRANSIT_BALANCE) {
        ISOException.throwIt(SW_MIN_TRANSIT_BALANCE);
    }

    // Check consistent transit state: should not currently be in transit
    if (entryStationId >= 0) {
        ISOException.throwIt(SW_INVALID_TRANSIT_STATE);
    }

    JCSystem.beginTransaction();

    // Get/assign entry station ID from request message
    entryStationId = Util.getShort(buffer, messageOffset);

    // Increment correlation ID
    correlationId++;

    JCSystem.commitTransaction();

    // Response Message: [[8-bytes UID], [2-bytes Correlation ID]]

    short offset = 0;

    // Append UID to response message
    offset = Util.arrayCopy(uid, (short) 0, buffer, offset, UID_LENGTH);

    // Append correlation ID to response message
    offset = Util.setShort(buffer, offset, correlationId);

    return offset;
}
 
Example 6
Source File: TransitApplet.java    From JCMathLib with MIT License 4 votes vote down vote up
/**
 * Processes a transit exit event. The passed-in transit fee is debited from
 * the account. The UID and the correlation ID are returned in the response
 * message.
 * 
 * Request Message: [1-byte Transit Fee]
 * 
 * Response Message: [[2-bytes UID], [2-bytes Correlation ID]]
 * 
 * @param buffer
 *            The APDU buffer
 * @param messageOffset
 *            The offset of the request message content in the APDU buffer
 * @param messageLength
 *            The length of the request message content.
 * @return The offset at which content can be appended to the response
 *         message
 */
private short processExit(byte[] buffer, short messageOffset,
        short messageLength) {

    // Request Message: [1-byte Transit Fee]

    if (messageLength != 1) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // Check minimum balance
    if (balance < MIN_TRANSIT_BALANCE) {
        ISOException.throwIt(SW_MIN_TRANSIT_BALANCE);
    }

    // Check consistent transit state: should be currently in transit
    if (entryStationId < 0) {
        ISOException.throwIt(SW_INVALID_TRANSIT_STATE);
    }

    // Get transit fee from request message
    byte transitFee = buffer[messageOffset];

    // Check potential negative balance
    if (balance < transitFee) {
        ISOException.throwIt(SW_NEGATIVE_BALANCE);
    }

    JCSystem.beginTransaction();

    // Debit transit fee
    balance -= transitFee;

    // Reset entry station ID
    entryStationId = -1;

    JCSystem.commitTransaction();

    // Response Message: [[8-bytes UID], [2-bytes Correlation ID]]

    short offset = 0;

    // Append UID to response message
    offset = Util.arrayCopy(uid, (short) 0, buffer, offset, UID_LENGTH);

    // Append correlation ID to response message
    offset = Util.setShort(buffer, offset, correlationId);

    return offset;
}
 
Example 7
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 8
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 4 votes vote down vote up
/**
 * GENERATE KEY APDU implementation.
 */
private void generateAsymetricKey(APDU apdu) {
  byte[] buffer = apdu.getBuffer();
  if (apdu.setIncomingAndReceive() != 2) {
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  }
  KeyPair key = getKey(buffer[ISO7816.OFFSET_CDATA]);
  if (buffer[ISO7816.OFFSET_P1] == (byte) 0x81) {
    if (!(key.getPublic()).isInitialized()) {
      ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
    }
  } else {
    if (!pins[PIN_INDEX_PW3].isValidated()) {
      ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }
    JCSystem.beginTransaction();
    key.genKeyPair();
    if (buffer[ISO7816.OFFSET_CDATA] == (byte)0xB6) {
      signatureCounter[0] = 0;
      signatureCounter[1] = 0;
      signatureCounter[2] = 0;
    }
    JCSystem.commitTransaction();
  }
  // Send the TLV data and public exponent using the APDU buffer.
  buffer[ISO7816.OFFSET_CDATA] = 0x7F;
  buffer[(short) (ISO7816.OFFSET_CDATA + 1)] = 0x49;
  buffer[(short) (ISO7816.OFFSET_CDATA + 2)] = (byte) 0x82;
  buffer[(short) (ISO7816.OFFSET_CDATA + 5)] = (byte) 0x82;
  short length = ((RSAPublicKey) key.getPublic()).getExponent(
      buffer, (short) (ISO7816.OFFSET_CDATA + 7));
  buffer[(short) (ISO7816.OFFSET_CDATA + 6)] = (byte) length;
  short pos = (short) (ISO7816.OFFSET_CDATA + 7 + length);
  buffer[pos] = (byte) 0x81;
  buffer[(short) (pos + 1)] = (byte) 0x82;
  Util.setShort(buffer, (short) (pos + 2), RSA_KEY_LENGTH_BYTES);
  Util.setShort(buffer, (short) (ISO7816.OFFSET_CDATA + 3),
                (short) (pos + RSA_KEY_LENGTH_BYTES - ISO7816.OFFSET_CDATA - 1));
  apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, (short) (length + 11));

  // And the modulus using get response.
  Util.setShort(commandChainingBuffer, TEMP_GET_RESPONSE_LENGTH, RSA_KEY_LENGTH_BYTES);
  ((RSAPublicKey) key.getPublic()).getModulus(commandChainingBuffer, TEMP_GET_RESPONSE_DATA);
  // Skip leading zero byte.
  if (commandChainingBuffer[TEMP_GET_RESPONSE_DATA] == 0) {
    Util.setShort(commandChainingBuffer, TEMP_GET_RESPONSE_OFFSET,
                  (short) (TEMP_GET_RESPONSE_DATA + 1));
  } else {
    Util.setShort(commandChainingBuffer, TEMP_GET_RESPONSE_OFFSET, TEMP_GET_RESPONSE_DATA);
  }
  commandChainingBuffer[TEMP_INS] = buffer[ISO7816.OFFSET_INS];
  ISOException.throwIt(ISO7816.SW_BYTES_REMAINING_00);
}
 
Example 9
Source File: PayPass.java    From CardExamples with The Unlicense 4 votes vote down vote up
public PayPass(byte[] bArray, short bOffset, byte bLength) {
    if (bLength != 27)
        ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
    // transaction starts
    JCSystem.beginTransaction();

    // set up and initialize all the DES encryption/descrytion ciphers used in the app
    DESKEY_KD_PERSO_L_EN = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES, false);
    DESKEY_KD_PERSO_R_DE = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES, false);
    DESKEY_KD_PERSO_L_DE = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES, false);
    DESKEY_KD_PERSO_R_EN = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES, false);
    CIPHER_KD_PERSO_L_EN = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false);
    CIPHER_KD_PERSO_R_DE = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false);
    CIPHER_KD_PERSO_L_DE = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false);
    CIPHER_KD_PERSO_R_EN = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false);

    // transaction ends
    JCSystem.commitTransaction();

    // define RAM buffers for faster operation
    CVC3_DATA = JCSystem.makeTransientByteArray((short) 16, JCSystem.CLEAR_ON_DESELECT);
    CMD_BUF = JCSystem.makeTransientByteArray((short) 261, JCSystem.CLEAR_ON_DESELECT);
    MAC = JCSystem.makeTransientByteArray((short) 8, JCSystem.CLEAR_ON_DESELECT);

    // on initialize the current state is not_alive
    state = not_alive;

    PROFILE = new Profile();

    // testing area
    // pre-personalization data
    // issuer supply
    PROFILE.VER_KMC = (byte) 0x01;  // MC version
    PROFILE.VER_KMC = bArray[bOffset];  // MC version
    PROFILE.KMC_ID[0] = (byte) 0x54;  // key id
    PROFILE.KMC_ID[1] = (byte) 0x13;
    PROFILE.KMC_ID[2] = (byte) 0x12;
    PROFILE.KMC_ID[3] = (byte) 0xFF;
    PROFILE.KMC_ID[4] = (byte) 0xFF;
    PROFILE.KMC_ID[5] = (byte) 0xFF;
    Util.arrayCopyNonAtomic(bArray, (short) (bOffset + 1), PROFILE.KMC_ID, (short) 0, (short) 6);
    PROFILE.KD_PERSO[0] = (byte) 0xA8;  // personalization key
    PROFILE.KD_PERSO[1] = (byte) 0x6A;
    PROFILE.KD_PERSO[2] = (byte) 0x3D;
    PROFILE.KD_PERSO[3] = (byte) 0x06;
    PROFILE.KD_PERSO[4] = (byte) 0xCA;
    PROFILE.KD_PERSO[5] = (byte) 0xE7;
    PROFILE.KD_PERSO[6] = (byte) 0x04;
    PROFILE.KD_PERSO[7] = (byte) 0x6A;
    PROFILE.KD_PERSO[8] = (byte) 0x10;
    PROFILE.KD_PERSO[9] = (byte) 0x63;
    PROFILE.KD_PERSO[10] = (byte) 0x58;
    PROFILE.KD_PERSO[11] = (byte) 0xD5;
    PROFILE.KD_PERSO[12] = (byte) 0xB8;
    PROFILE.KD_PERSO[13] = (byte) 0x23;
    PROFILE.KD_PERSO[14] = (byte) 0x9C;
    PROFILE.KD_PERSO[15] = (byte) 0xBE;
    Util.arrayCopyNonAtomic(bArray, (short) (bOffset + 7), PROFILE.KD_PERSO, (short) 0, (short) 16);
    PROFILE.CSN[0] = (byte) 0x89;
    PROFILE.CSN[1] = (byte) 0xAA;
    PROFILE.CSN[2] = (byte) 0x7F;
    PROFILE.CSN[3] = (byte) 0x00;
    Util.arrayCopyNonAtomic(bArray, (short) (bOffset + 23), PROFILE.CSN, (short) 0, (short) 4);
    // end issuer supply

    // profile can now be considered in personalization state
    PROFILE.STATE = PERSO;
}
 
Example 10
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 3 votes vote down vote up
/**
 * Udpate the PIN and its length in a transaction.
 * @param pinId which PIN will be updated.
 * @param data contains the new PIN.
 * @param dataOffset first byte of the new PIN in the data array.
 * @param newLength the new PIN length.
 */
private void updatePIN(short pinId, byte[] data, short dataOffset, byte newLength) {
  JCSystem.beginTransaction();
  pins[pinId].update(data, dataOffset, newLength);
  pinLength[pinId] = newLength;
  JCSystem.commitTransaction();
}