Java Code Examples for javacard.framework.Util#getShort()

The following examples show how to use javacard.framework.Util#getShort() . 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: UtilTLV.java    From GidsApplet with GNU General Public License v3.0 5 votes vote down vote up
public static short GetBERTLVDataLen(byte[] buf, short offset, short len) {
    short size = 0;
    short sizeforsize = 0;
    short i = 1;

    if ((buf[offset] & 0x1F) != 0x1F) {
        // simplified tag
    } else {
        // tag start with all 5 last bits to 1
        // skip the tag
        while (((buf[(short) (offset + i)] & 0x80) != 0) && ((short)(i+offset)) < len) {
            i++;
        }
        // pass the last byte of the tag
        i+=1;
    }
    // check the size
    if ((buf[(short) (offset + i)] & 0x80) != 0) {
        // size encoded in many bytes
        sizeforsize = (short) (buf[(short) (offset + i)] & 0x7F);
        if (sizeforsize > 2) {
            // more than two bytes for encoding => not something than we can handle
            return 0;
        } else if (sizeforsize == 1) {
            size = Util.makeShort((byte) 0,buf[(short) (offset + i + 1)]);
        } else if (sizeforsize == 2) {
            size = Util.getShort(buf, (short) (offset + i + 1));
        }
    } else {
        // size encode in one byte
        size = Util.makeShort((byte) 0,buf[(short) (offset + i)]);
    }
    return size;
}
 
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: 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 4
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 5
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 6
Source File: NdefApplet.java    From openjavacard-ndef with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Process an UPDATE BINARY command
 *
 * Supports simple writes at any offset.
 *
 * The amount of data that can be written in one
 * operation is limited both by maximum C-APDU
 * length and the maximum write size NDEF_MAX_WRITE.
 *
 * @param apdu to process
 * @throws ISOException on error
 */
private void processUpdateBinary(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();

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

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

    // receive data
    short lc = apdu.setIncomingAndReceive();

    // check the input size
    if(lc > NDEF_MAX_WRITE) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // file limit checks
    short limit = (short)(offset + lc);
    if(limit < 0 || limit >= file.length) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // perform the update
    Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, file, offset, lc);
}
 
Example 7
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 5 votes vote down vote up
private short addKeyPart(byte part, byte[] data, short offset, KeyPair key) {
  short size = Util.getShort(commandChainingBuffer, TEMP_PUT_KEY_EXPECTED_CHUNK_SIZE);
  short nextSize = RSA_KEY_HALF_LENGTH_BYTES;
  switch (part) {
    case KEY_PART_E:
      ((RSAPublicKey) key.getPublic()).setExponent(data, offset, size);
      break;
    case KEY_PART_PRIME_P:
      ((RSAPrivateCrtKey) key.getPrivate()).setP(data, offset, size);
      break;
    case KEY_PART_PRIME_Q:
      ((RSAPrivateCrtKey) key.getPrivate()).setQ(data, offset, size);
      break;
    case KEY_PART_PARAM_PQ:
      ((RSAPrivateCrtKey) key.getPrivate()).setPQ(data, offset, size);
      break;
    case KEY_PART_PARAM_DP1:
      ((RSAPrivateCrtKey) key.getPrivate()).setDP1(data, offset, size);
      break;
    case KEY_PART_PARAM_DQ1:
      ((RSAPrivateCrtKey) key.getPrivate()).setDQ1(data, offset, size);
      nextSize = RSA_KEY_LENGTH_BYTES;
      break;

    case KEY_PART_N:
      ((RSAPublicKey) key.getPublic()).setModulus(data, offset, RSA_KEY_LENGTH_BYTES);
      if (!key.getPrivate().isInitialized() ||
          !key.getPublic().isInitialized()) {
        ISOException.throwIt(ISO7816.SW_DATA_INVALID);
      }
      return (short) (offset + RSA_KEY_LENGTH_BYTES);
  }
  Util.setShort(commandChainingBuffer, TEMP_PUT_KEY_EXPECTED_CHUNK_SIZE, nextSize);
  return (short) (offset + size);
}
 
Example 8
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * This function allows to decrypt a secure channel message
 *  
 *  ins: 0x82
 *  
 *  p1: 0x00 (RFU)
 *  p2: 0x00 (RFU)
 *  data: [IV(16b) | data_size(2b) | encrypted_command | mac_size(2b) | mac]
    *  
    *  return: [decrypted command]
    *   
 */
private short ProcessSecureChannel(APDU apdu, byte[] buffer){
	
       short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
       short offset = ISO7816.OFFSET_CDATA;
       
       if (!initialized_secure_channel){
       	ISOException.throwIt(SW_SECURE_CHANNEL_UNINITIALIZED);
       }
       
       // check hmac
       if (bytesLeft<18)
       	ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       short sizein = Util.getShort(buffer, (short) (offset+SIZE_SC_IV));
       if (bytesLeft<(short)(SIZE_SC_IV+2+sizein+2))
       	ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       short sizemac= Util.getShort(buffer, (short) (offset+SIZE_SC_IV+2+sizein));
       if (sizemac != (short)20)
       	ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_MAC);
       if (bytesLeft<(short)(SIZE_SC_IV+2+sizein+2+sizemac))
       	ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       HmacSha160.computeHmacSha160(sc_buffer, OFFSET_SC_MACKEY, SIZE_SC_MACKEY, buffer, offset, (short)(SIZE_SC_IV+2+sizein), recvBuffer, (short)0);
       if ( Util.arrayCompare(recvBuffer, (short)0, buffer, (short)(offset+SIZE_SC_IV+2+sizein+2), (short)20) != (byte)0 )
       	ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_MAC);
       
       // process IV
       // IV received from client should be odd and strictly greater than locally saved IV
       // IV should be random (the 12 first bytes), never reused (the last 4 bytes counter) and different for send and receive
       if ((buffer[(short)(offset+SIZE_SC_IV-(short)1)] & (byte)0x01)==0x00)// should be odd
       	ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_IV);
       if ( !Biginteger.lessThan(sc_buffer, OFFSET_SC_IV_COUNTER, buffer, (short)(offset+SIZE_SC_IV_RANDOM), SIZE_SC_IV_COUNTER ) ) //and greater than local IV
       	ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_IV);
       // update local IV
       Util.arrayCopy(buffer, (short)(offset+SIZE_SC_IV_RANDOM), sc_buffer, OFFSET_SC_IV_COUNTER, SIZE_SC_IV_COUNTER);
       Biginteger.add1_carry(sc_buffer, OFFSET_SC_IV_COUNTER, SIZE_SC_IV_COUNTER);
    	randomData.generateData(sc_buffer, OFFSET_SC_IV_RANDOM, SIZE_SC_IV_RANDOM);
    	sc_aes128_cbc.init(sc_sessionkey, Cipher.MODE_DECRYPT, buffer, offset, SIZE_SC_IV);
       offset+=SIZE_SC_IV;
       bytesLeft-=SIZE_SC_IV;
       
       //decrypt command
       offset+=2;
       bytesLeft-=2;
       if (bytesLeft<sizein)
       	ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       short sizeout=sc_aes128_cbc.doFinal(buffer, offset, sizein, buffer, (short) (0));
       return sizeout;
}
 
Example 9
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 10
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
   * This function encrypts/decrypt a given message with a 16bytes secret key derived from the 2FA key.
   * It also returns an id derived from the 2FA key.
   * This is used to privately exchange tx data between the hw wallet and the 2FA device.
* 
   * Algorithms: 
   *      id_2FA is hmac-sha1(secret_2FA, "id_2FA"), 
   *      key_2FA is hmac-sha1(secret_2FA, "key_2FA"), 
   *      message encrypted using AES
   *
   * ins: 0x76
* p1: 0x00 for encryption, 0x01 for decryption  
* p2: Init-Update-Finalize
* data(init): IF_ENCRYPT: none ELSE: [IV(16b)]
   * data(update/finalize): [chunk_size(2b) | chunk_data]
* 
* return(init): IF_ENCRYPT:[IV(16b) | id_2FA(20b)] ELSE: none
   * return(update/finalize): [chunk_size(2b) | chunk_data]
* 
*
   */
  private short CryptTransaction2FA(APDU apdu, byte[] buffer){
  	// check that PIN[0] has been entered previously
  	if (!pins[0].isValidated())
	ISOException.throwIt(SW_UNAUTHORIZED);
      
  	// check that 2FA is enabled
if (!needs_2FA)
	ISOException.throwIt(SW_2FA_UNINITIALIZED_KEY);
  	
      byte ciph_dir = buffer[ISO7816.OFFSET_P1];
      byte ciph_op = buffer[ISO7816.OFFSET_P2];
      short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
      short dataOffset = ISO7816.OFFSET_CDATA;
      
      short IVlength=(short)16;
      switch(ciph_op){
          case OP_INIT:
              if (ciph_dir!=Cipher.MODE_ENCRYPT &&  ciph_dir!=Cipher.MODE_DECRYPT )
                  ISOException.throwIt(SW_INVALID_PARAMETER);
              
              if (ciph_dir==Cipher.MODE_ENCRYPT){
                  randomData.generateData(buffer,(short)0, IVlength);
                  aes128_cbc.init(key_2FA, Cipher.MODE_ENCRYPT, buffer, (short)0, IVlength);
                  Util.arrayCopyNonAtomic(data2FA, OFFSET_2FA_ID, buffer, (short)IVlength, (short)20);
                  return (short)(IVlength + 20);
              }
              if (ciph_dir==Cipher.MODE_DECRYPT){
                  aes128_cbc.init(key_2FA, Cipher.MODE_DECRYPT, buffer, dataOffset, IVlength);
                  return (short)0;
              }
              break;
          case OP_PROCESS:
          case OP_FINALIZE:
              if (bytesLeft < 2)
              	ISOException.throwIt(SW_INVALID_PARAMETER); 
              short size = Util.getShort(buffer, dataOffset);
              if (bytesLeft < (short) (2 + size))
              	ISOException.throwIt(SW_INVALID_PARAMETER); 
              
              short sizeout=0;
              if (ciph_op == OP_PROCESS){
                  sizeout=aes128_cbc.update(buffer, (short) (dataOffset + 2), size, buffer, (short) 2);
              }
              else {// ciph_op == OP_FINALIZE
                  sizeout=aes128_cbc.doFinal(buffer, (short) (dataOffset + 2), size, buffer, (short) 2);
          	}
              // Also copies the Short size information
              Util.setShort(buffer,(short)0,  sizeout);
              return (short) (sizeout + 2);
              
          default:
              ISOException.throwIt(SW_INCORRECT_P2);    
      } 
      return (short)0;
  }
 
Example 11
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
   * This function signs a given transaction hash with a std or the last extended key
   * If 2FA is enabled, a HMAC must be provided as an additional security layer. 
* 
   * ins: 0x7A
* p1: key number or 0xFF for the last derived Bip32 extended key  
* p2: 0x00
* data: [hash(32b) | option: 2FA-flag(2b)|hmac(20b)]
* 
* return: [sig ]
* 
   */
  private short SignTransactionHash(APDU apdu, byte[] buffer){
  	
  	// check that PIN[0] has been entered previously
if (!pins[0].isValidated())
	ISOException.throwIt(SW_UNAUTHORIZED);

  	byte key_nb = buffer[ISO7816.OFFSET_P1];
if ( (key_nb!=(byte)0xFF) && ((key_nb < 0) || (key_nb >= MAX_NUM_KEYS)) )
	ISOException.throwIt(SW_INCORRECT_P1);

  	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
if (bytesLeft<MessageDigest.LENGTH_SHA_256)
	ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  	
  	// check whether the seed is initialized
if (key_nb==(byte)0xFF && !bip32_seeded)
	ISOException.throwIt(SW_BIP32_UNINITIALIZED_SEED);
  	
// check 2FA if required
if(needs_2FA){
	// check data length
	if (bytesLeft<MessageDigest.LENGTH_SHA_256+MessageDigest.LENGTH_SHA+(short)2)
		ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
	// check flag for 2fa_hmac_chalresp
	short hmac_flags= Util.getShort(buffer, (short)(ISO7816.OFFSET_CDATA+32));
	if (hmac_flags!=HMAC_CHALRESP_2FA)
		ISOException.throwIt(SW_INCORRECT_ALG);
	// hmac of 64-bytes msg: ( 32bytes tx_hash | 32bytes 0xCC-padding)
	Util.arrayCopyNonAtomic(buffer, (short)ISO7816.OFFSET_CDATA, recvBuffer, (short)0, (short)32);
	Util.arrayFillNonAtomic(recvBuffer, (short)32, (short)32, (byte)0xCC);
	HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, recvBuffer, (short)0, (short)64, recvBuffer, (short)64);
	if (Util.arrayCompare(buffer, (short)(ISO7816.OFFSET_CDATA+32+2), recvBuffer, (short)64, (short)20)!=0)
		ISOException.throwIt(SW_SIGNATURE_INVALID);
}

// hash+sign singlehash
  	if (key_nb==(byte)0xFF)
  		sigECDSA.init(bip32_extendedkey, Signature.MODE_SIGN);
  	else{
  		Key key= eckeys[key_nb];
  		// check type and size
  		if ((key == null) || !key.isInitialized())
  			ISOException.throwIt(SW_INCORRECT_P1);
  		if (key.getType() != KeyBuilder.TYPE_EC_FP_PRIVATE)
  			ISOException.throwIt(SW_INCORRECT_ALG);		
  		if (key.getSize()!= LENGTH_EC_FP_256)
  			ISOException.throwIt(SW_INCORRECT_ALG);
  		sigECDSA.init(key, Signature.MODE_SIGN);
  	}
      short sign_size= sigECDSA.signPreComputedHash(buffer, ISO7816.OFFSET_CDATA, MessageDigest.LENGTH_SHA_256, buffer, (short)0);
      return sign_size;
  }
 
Example 12
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 4 votes vote down vote up
private void decrypt(APDU apdu) {
  byte[] buffer = apdu.getBuffer();
  // PW1 with 0x82
  if (!pins[PIN_INDEX_PW1].isValidated() || !pinSubmitted[1]) {
    ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
  }
  if (!confidentialityKey.getPrivate().isInitialized()) {
    ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
  }
  boolean firstCommand = (commandChainingBuffer[TEMP_INS] != buffer[ISO7816.OFFSET_INS]);
  // Mark the command chain as bad so it stays in this state in case of exception.
  short len = apdu.setIncomingAndReceive();
  if (len < 1) {
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  }
  if (firstCommand) {
    Util.arrayCopyNonAtomic(buffer, (short) (ISO7816.OFFSET_CDATA + 1), commandChainingBuffer,
                            TEMP_GET_RESPONSE_DATA, (short) (len - 1));
    len = (short) (len - 1);
  } else {
    short existing = Util.getShort(commandChainingBuffer, TEMP_GET_RESPONSE_LENGTH);
    if ((short) (len + existing) > RSA_KEY_LENGTH_BYTES) {
      ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, commandChainingBuffer,
                            (short) (TEMP_GET_RESPONSE_DATA + existing), len);
    len += existing;
  }
  if (len < RSA_KEY_LENGTH_BYTES) {
    commandChainingBuffer[TEMP_INS] = CMD_COMPUTE_PSO;
    Util.setShort(commandChainingBuffer, TEMP_GET_RESPONSE_LENGTH, len);
    return;  // For compatibily with GPG
  }
  // We have enough bytes to decrypt.
  cipherRSA.init(confidentialityKey.getPrivate(), Cipher.MODE_DECRYPT);
  len = cipherRSA.doFinal(commandChainingBuffer, TEMP_GET_RESPONSE_DATA, RSA_KEY_LENGTH_BYTES,
                          buffer, (short) 0);
  // Clear command chaining buffer to make ready for next operation.
  Util.arrayFillNonAtomic(commandChainingBuffer, (short) 0, (short) commandChainingBuffer.length, (byte) 0);
  apdu.setOutgoingAndSend((short) 0, len);
}
 
Example 13
Source File: UtilTLV.java    From openjavacard-ndef with GNU General Public License v3.0 4 votes vote down vote up
/**
 * \brief Decode the length field of a TLV-entry.
 *
 * The length field itself can be 1, 2 or 3 bytes long:
 * 	- If the length is between 0 and 127, it is 1 byte long.
 * 	- If the length is between 128 and 255, it is 2 bytes long.
 *		The first byte is 0x81 to indicate this.
 *	- If the length is between 256 and 65535, it is 3 bytes long.
 *		The first byte is 0x82, the following 2 contain the actual length.
 *		Note: Only lengths up to 0x7FFF (32767) are supported here, because a short in Java is signed.
 *
 * \param buf The buffer containing the length field.
 *
 * \param offset The offset at where the length field starts.
 *
 * \param length The length of the buffer (buf). This is to prevent that the index gets out of bounds.
 *
 * \return The (positive) length encoded by the length field, or in case of an error, -1.
 *
 * \throw InvalidArgumentsException If offset is too big for a signed Java short
 *                                  If the first byte of the length field is invalid
 */
public static short decodeLengthField(byte[] buf, short offset) {
    if(buf[offset] == (byte)0x82) { // 256..65535
        // Check for short overflow
        // (In Java, a short is signed: positive values are 0000..7FFF)
        if(buf[(short)(offset+1)] < 0) { // 80..FF
            return -1;
        }
        return Util.getShort(buf, (short)(offset+1));
    } else if(buf[offset] == (byte)0x81) {
        return (short) ( 0x00FF & buf[(short)(offset+1)]);
    } else if(buf[offset] > 0) { // 00..7F
        return (short) ( 0x007F & buf[offset]);
    } else {
        return -1;
    }
}
 
Example 14
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 15
Source File: NdefApplet.java    From openjavacard-ndef with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Main constructor
 *
 * This will construct and initialize an instance
 * of this applet according to the provided app data.
 *
 * @param buf containing application data
 * @param off offset of app data in buf
 * @param len length of app data in buf
 */
protected NdefApplet(byte[] buf, short off, byte len) {

    short initSize = DEFAULT_NDEF_DATA_SIZE;
    byte initReadAccess = DEFAULT_NDEF_READ_ACCESS;
    byte initWriteAccess = DEFAULT_NDEF_WRITE_ACCESS;
    byte[] initBuf = null;
    short  initOff = 0;
    short  initLen = 0;

    // create variables
    vars = JCSystem.makeTransientShortArray(NUM_VARS, JCSystem.CLEAR_ON_DESELECT);

    // process application data
    if(FEATURE_INSTALL_PARAMETERS) {
        // check TLV consistency
        if (!UtilTLV.isTLVconsistent(buf, off, len)) {
            ISOException.throwIt(ISO7816.SW_DATA_INVALID);
        }

        // DATA INITIAL
        short initTag = UtilTLV.findTag(buf, off, len, AD_TAG_NDEF_DATA_INITIAL);
        if (initTag >= 0) {
            initBuf = buf;
            initLen = UtilTLV.decodeLengthField(buf, (short) (initTag + 1));
            initOff = (short) (initTag + 1 + UtilTLV.getLengthFieldLength(initLen));
            // restrict writing, can be overridden using DATA ACCESS
            initWriteAccess = FILE_ACCESS_NONE;
            // adjust size, can be overridden
            initSize = (short) (2 + initLen);
        }

        // DATA ACCESS
        short tagAccess = UtilTLV.findTag(buf, off, len, AD_TAG_NDEF_DATA_ACCESS);
        if (tagAccess >= 0) {
            short accessLen = UtilTLV.decodeLengthField(buf, (short) (tagAccess + 1));
            if (accessLen != 2) {
                ISOException.throwIt(ISO7816.SW_DATA_INVALID);
            }
            initReadAccess = buf[(short) (tagAccess + 2)];
            initWriteAccess = buf[(short) (tagAccess + 3)];
        }

        // DATA SIZE
        short tagSize = UtilTLV.findTag(buf, off, len, AD_TAG_NDEF_DATA_SIZE);
        if (tagSize >= 0) {
            short sizeLen = UtilTLV.decodeLengthField(buf, (short) (tagSize + 1));
            if (sizeLen != 2) {
                ISOException.throwIt(ISO7816.SW_DATA_INVALID);
            }
            initSize = Util.getShort(buf, (short) (tagSize + 2));
            if (initSize < 0) {
                ISOException.throwIt(ISO7816.SW_DATA_INVALID);
            }
        }
    }

    // squash write access if not supported
    if(!FEATURE_WRITING) {
        initWriteAccess = FILE_ACCESS_NONE;
    }

    // set up access
    dataReadAccess = initReadAccess;
    dataWriteAccess = initWriteAccess;

    // create file contents
    capsFile = makeCaps(initSize, initReadAccess, initWriteAccess);
    dataFile = makeData(initSize, initBuf, initOff, initLen);
}
 
Example 16
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 17
Source File: EC_Consts.java    From ECTester with MIT License 4 votes vote down vote up
public static short transformParameter(short transformation, byte[] buffer, short offset, short length) {
    if (transformation == TRANSFORMATION_NONE) {
        return length;
    }

    short transformationMask = TRANSFORMATION_FIXED;
    while (transformationMask <= TRANSFORMATION_04_MASK) {
        short transformationPart = (short) (transformationMask & transformation);
        switch (transformationPart) {
            case (short) 0:
                break;
            case TRANSFORMATION_FIXED:
                if (length >= 1) {
                    buffer[offset] = (byte) 0xcc;
                    buffer[(short) (offset + length - 1)] = (byte) 0xcc;
                }
                break;
            case TRANSFORMATION_FULLRANDOM:
                randomData.generateData(buffer, offset, length);
                break;
            case TRANSFORMATION_ONEBYTERANDOM:
                short first = Util.getShort(buffer, (short) 0); // save first two bytes

                randomData.generateData(buffer, (short) 0, (short) 2); // generate position
                short rngPos = Util.getShort(buffer, (short) 0); // save generated position

                Util.setShort(buffer, (short) 0, first); // restore first two bytes

                if (rngPos < 0) { // make positive
                    rngPos = (short) -rngPos;
                }
                rngPos %= length; // make < param length

                byte original = buffer[rngPos];
                do {
                    randomData.generateData(buffer, rngPos, (short) 1);
                } while (original == buffer[rngPos]);
                break;
            case TRANSFORMATION_ZERO:
                Util.arrayFillNonAtomic(buffer, offset, length, (byte) 0);
                break;
            case TRANSFORMATION_ONE:
                Util.arrayFillNonAtomic(buffer, offset, length, (byte) 0);
                buffer[(short) (offset + length)] = (byte) 1;
                break;
            case TRANSFORMATION_MAX:
                Util.arrayFillNonAtomic(buffer, offset, length, (byte) 1);
                break;
            case TRANSFORMATION_INCREMENT:
                short index = (short) (offset + length - 1);
                byte value;
                do {
                    value = buffer[index];
                    buffer[index--] = ++value;
                } while (value == (byte) 0 && index >= offset);
                break;
            case TRANSFORMATION_INFINITY:
                Util.arrayFillNonAtomic(buffer, offset, length, (byte) 0);
                length = 1;
                break;
            case TRANSFORMATION_COMPRESS_HYBRID:
            case TRANSFORMATION_COMPRESS:
                if ((short) (length % 2) != 1) {
                    // an uncompressed point should have odd length (since 1 byte type, + 2 * coords)
                    ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
                }
                short half = (short) ((short) (length - 1) / 2);
                byte yLSB = buffer[(short) (offset + length)];
                byte yBit = (byte) (yLSB & 0x01);
                if (yBit == 1) {
                    buffer[offset] = 3;
                } else {
                    buffer[offset] = 2;
                }

                if (transformationPart == TRANSFORMATION_COMPRESS) {
                    length = (short) (half + 1);
                } else {
                    buffer[offset] += 4;
                }
                break;
            case TRANSFORMATION_04_MASK:
                buffer[offset] = 4;
                break;
            default:
                ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
        }
        transformationMask = (short) (transformationMask << 1);
    }
    return length;
}
 
Example 18
Source File: UtilTLV.java    From GidsApplet with GNU General Public License v3.0 4 votes vote down vote up
public static short CheckBERTLV(byte[] buf, short offset, short len) {
    short size = 0;
    short sizeforsize = 0;
    short i = 1;
    short totalsize = 0;

    if ((buf[offset] & 0x1F) != 0x1F) {
        // simplified tag
    } else {
        // tag start with all 5 last bits to 1
        // skip the tag
        while (((buf[(short) (offset + i)] & 0x80) != 0) && i < len) {
            i++;
        }
        // pass the last byte of the tag
        i+=1;
    }
    if ((short) (i+1) >len) {
        return 0;
    }
    // check the size
    if ((buf[(short) (offset + i)] & 0x80) != 0) {
        // size encoded in many bytes
        sizeforsize = (short) (buf[(short) (offset + i)] & 0x7F);
        if ((short) (i+1+sizeforsize) >len) {
            return 0;
        }
        if (sizeforsize > (short) 2) {
            // more than two bytes for encoding => not something than we can handle
            return 0;
        } else if (sizeforsize == (short) 1) {
            if ((short) (offset + i + 1 + sizeforsize) > len) {
                return 0;
            }
            size = Util.makeShort((byte) 0,buf[(short) (offset + i + 1)]);
        } else if (sizeforsize == 2) {
            totalsize = (short) (i + 1 + sizeforsize + size);
            if ((short) (offset + i + 1 + sizeforsize) > len) {
                return (short) 0;
            }
            size = Util.getShort(buf, (short) (offset + i + 1));
        }
    } else {
        // size encode in one byte
        size = Util.makeShort((byte) 0,buf[(short) (offset + i)]);
    }
    totalsize = (short) (i + 1 + sizeforsize + size);
    if (totalsize < (short) 240 && (short) (offset +  totalsize) > len) {
        return (short) 0;
    }
    return totalsize;
}
 
Example 19
Source File: UtilTLV.java    From GidsApplet with GNU General Public License v3.0 4 votes vote down vote up
/**
 * \brief Decode the length field of a TLV-entry.
 *
 * The length field itself can be 1, 2 or 3 bytes long:
 * 	- If the length is between 0 and 127, it is 1 byte long.
 * 	- If the length is between 128 and 255, it is 2 bytes long.
 *		The first byte is 0x81 to indicate this.
 *	- If the length is between 256 and 65535, it is 3 bytes long.
 *		The first byte is 0x82, the following 2 contain the actual length.
 *		Note: Only lengths up to 0x7FFF (32767) are supported here, because a short in Java is signed.
 *
 * \param buf The buffer containing the length field.
 *
 * \param offset The offset at where the length field starts.
 *
 * \param length The length of the buffer (buf). This is to prevent that the index gets out of bounds.
 *
 * \return The (positive) length encoded by the length field, or in case of an error, -1.
 *
 * \throw InvalidArgumentsException If offset is too big for a signed Java short
 *                                  If the first byte of the length field is invalid
 */
public static short decodeLengthField(byte[] buf, short offset) throws InvalidArgumentsException {
    if(buf[offset] == (byte)0x82) { // 256..65535
        // Check for short overflow
        // (In Java, a short is signed: positive values are 0000..7FFF)
        if(buf[(short)(offset+1)] < 0) { // 80..FF
            throw InvalidArgumentsException.getInstance();
        }
        return Util.getShort(buf, (short)(offset+1));
    } else if(buf[offset] == (byte)0x81) {
        return (short) ( 0x00FF & buf[(short)(offset+1)]);
    } else if(buf[offset] > 0) { // 00..7F
        return (short) ( 0x007F & buf[offset]);
    } else {
        throw InvalidArgumentsException.getInstance();
    }
}
 
Example 20
Source File: UtilTLV.java    From IsoApplet with GNU General Public License v3.0 4 votes vote down vote up
/**
 * \brief Decode the length field of a TLV-entry.
 *
 * The length field itself can be 1, 2 or 3 bytes long:
 * 	- If the length is between 0 and 127, it is 1 byte long.
 * 	- If the length is between 128 and 255, it is 2 bytes long.
 *		The first byte is 0x81 to indicate this.
 *	- If the length is between 256 and 65535, it is 3 bytes long.
 *		The first byte is 0x82, the following 2 contain the actual length.
 *		Note: Only lengths up to 0x7FFF (32767) are supported here, because a short in Java is signed.
 *
 * \param buf The buffer containing the length field.
 *
 * \param offset The offset at where the length field starts.
 *
 * \param length The length of the buffer (buf). This is to prevent that the index gets out of bounds.
 *
 * \return The (positive) length encoded by the length field, or in case of an error, -1.
 *
 * \throw InvalidArgumentsException If offset is too big for a signed Java short
 *                                  If the first byte of the length field is invalid
 */
public static short decodeLengthField(byte[] buf, short offset) throws InvalidArgumentsException {
    if(buf[offset] == (byte)0x82) { // 256..65535
        // Check for short overflow
        // (In Java, a short is signed: positive values are 0000..7FFF)
        if(buf[(short)(offset+1)] < 0) { // 80..FF
            throw InvalidArgumentsException.getInstance();
        }
        return Util.getShort(buf, (short)(offset+1));
    } else if(buf[offset] == (byte)0x81) {
        return (short) ( 0x00FF & buf[(short)(offset+1)]);
    } else if(buf[offset] > 0) { // 00..7F
        return (short) ( 0x007F & buf[offset]);
    } else {
        throw InvalidArgumentsException.getInstance();
    }
}