Java Code Examples for javacard.framework.ISO7816#OFFSET_P1

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

    PM.check(PM.TRAP_INT_ADD_1);    
    //Integer num_add_1 = new Integer(dataLen, (short) 0, apdubuf, ISO7816.OFFSET_CDATA);
    Integer num_add_1 = m_testINT1;
    num_add_1.fromByteArray(apdubuf, ISO7816.OFFSET_CDATA, p1);
    PM.check(PM.TRAP_INT_ADD_2);
    //Integer num_add_2 = new Integer((short) (dataLen - p1), (short) 0, apdubuf, (short) (ISO7816.OFFSET_CDATA + p1));
    Integer num_add_2 = m_testINT2;
    num_add_2.fromByteArray(apdubuf, (short) (ISO7816.OFFSET_CDATA + p1), p1);
    PM.check(PM.TRAP_INT_ADD_3);
    num_add_1.add(num_add_2);
    PM.check(PM.TRAP_INT_ADD_4);
    short len = num_add_1.toByteArray(apdubuf, (short) 0);
    apdu.setOutgoingAndSend((short) 0, len);
}
 
Example 2
Source File: OCUnitTests.java    From JCMathLib with MIT License 6 votes vote down vote up
void test_BN_SUB(APDU apdu, short dataLen) {
    byte[] apdubuf = apdu.getBuffer();
    short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);

    PM.check(PM.TRAP_BN_SUB_1);
    Bignat sub1 = m_testBN1;
    sub1.set_size(p1);
    PM.check(PM.TRAP_BN_SUB_2);
    Bignat sub2 = m_testBN2;
    sub2.set_size((short) (dataLen - p1));
    PM.check(PM.TRAP_BN_SUB_3);
    Bignat result = m_testBN3;
    result.set_size((short) (p1 + 1));
    PM.check(PM.TRAP_BN_SUB_4);
    sub1.from_byte_array(dataLen, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
    sub2.from_byte_array(dataLen, (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
    PM.check(PM.TRAP_BN_SUB_5);
    result.copy(sub1);
    PM.check(PM.TRAP_BN_SUB_6);
    result.subtract(sub2);
    PM.check(PM.TRAP_BN_SUB_7);
    short len = result.copy_to_buffer(apdubuf, (short) 0);
    apdu.setOutgoingAndSend((short) 0, len);
}
 
Example 3
Source File: IsoApplet.java    From IsoApplet with GNU General Public License v3.0 6 votes vote down vote up
/**
 * \brief Process the PUT DATA apdu (INS=DB).
 *
 * PUT DATA is currently used for private key import.
 *
 * \throw ISOException SW_SECURITY_STATUS_NOT_SATISFIED, SW_INCORRECT_P1P2
 */
private void processPutData(APDU apdu) throws ISOException {
    byte[] buf = apdu.getBuffer();
    byte p1 = buf[ISO7816.OFFSET_P1];
    byte p2 = buf[ISO7816.OFFSET_P2];

    if( ! pin.isValidated() ) {
        ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
    }

    if(p1 == (byte) 0x3F && p2 == (byte) 0xFF) {
        if( ! DEF_PRIVATE_KEY_IMPORT_ALLOWED) {
            ISOException.throwIt(SW_COMMAND_NOT_ALLOWED_GENERAL);
        }
        importPrivateKey(apdu);
    } else {
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }
}
 
Example 4
Source File: OCUnitTests.java    From JCMathLib with MIT License 6 votes vote down vote up
void test_BN_MUL_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_MUL_MOD_1);    
    Bignat num1 = m_testBN1;
    num1.set_size(p1);
    PM.check(PM.TRAP_BN_MUL_MOD_2);
    Bignat num2 = m_testBN2;
    num2.set_size(p2);
    PM.check(PM.TRAP_BN_MUL_MOD_3);
    Bignat mod = m_testBN3;
    mod.set_size((short) (dataLen - p1 - p2));
    PM.check(PM.TRAP_BN_MUL_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_MUL_MOD_5);
    num1.mod_mult(num1, num2, mod);
    PM.check(PM.TRAP_BN_MUL_MOD_6);
    short len = num1.copy_to_buffer(apdubuf, (short) 0);
    apdu.setOutgoingAndSend((short) 0, len);
}
 
Example 5
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 5 votes vote down vote up
/**
 * RESET RETRY COUNTER ADPU implementation.
 */
private void resetRetryCounter(APDU apdu) {
  byte buffer[] = apdu.getBuffer();
  short length = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
  if (apdu.setIncomingAndReceive() != length) {
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  }

  if (buffer[ISO7816.OFFSET_P2] != (byte) 0x81) {
    ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
  }
  if (buffer[ISO7816.OFFSET_P1] == (byte) 0) {
    // We need to check RC then update P1 (if RC is set).
    byte rcLength = pinLength[PIN_INDEX_RC];
    if (pins[PIN_INDEX_RC].getTriesRemaining() == 0 || rcLength == 0) {
      ISOException.throwIt(SW_PIN_BLOCKED);
    }
    if (length < rcLength + MIN_PIN1_LENGTH ||
        length > rcLength + MAX_PIN_LENGTH) {
      ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    if (pins[PIN_INDEX_RC].check(buffer, ISO7816.OFFSET_CDATA, rcLength)) {
      updatePIN(PIN_INDEX_PW1, buffer, (short) (ISO7816.OFFSET_CDATA + rcLength),
                (byte) (length - rcLength));
    } else {
      ISOException.throwIt((short) (SW_PIN_FAILED_00 + pins[PIN_INDEX_RC].getTriesRemaining()));
    }
  } else if (buffer[ISO7816.OFFSET_P1] == (byte) 2) {
    // Resetting by assuming that PW3 was submitted.
    if (!pins[PIN_INDEX_PW3].isValidated()) {
      ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }
    if (length < MIN_PIN1_LENGTH || length > MAX_PIN_LENGTH) {
      ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    updatePIN(PIN_INDEX_PW1, buffer, ISO7816.OFFSET_CDATA, (byte) length);
  } else {
    ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
  }
}
 
Example 6
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 7
Source File: OCUnitTests.java    From JCMathLib with MIT License 5 votes vote down vote up
void test_INT_STR(APDU apdu, short dataLen) {
    byte[] apdubuf = apdu.getBuffer();
    short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);

    PM.check(PM.TRAP_INT_STR_1);
    //Integer num_int = new Integer(dataLen, (short) 0, apdubuf, ISO7816.OFFSET_CDATA);
    Integer num_int = m_testINT1;
    num_int.fromByteArray(apdubuf, ISO7816.OFFSET_CDATA, dataLen);
    PM.check(PM.TRAP_INT_STR_2);
    short len = num_int.toByteArray(apdubuf, (short) 0);
    apdu.setOutgoingAndSend((short) 0, len);
}
 
Example 8
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 5 votes vote down vote up
private static void handleGetOperationMode(APDU apdu) throws ISOException {
 byte[] buffer = apdu.getBuffer();
 if (buffer[ISO7816.OFFSET_P1] == P1_GET_OPERATION_MODE) {
  buffer[0] = currentMode;
 }
 else
 if (buffer[ISO7816.OFFSET_P1] == P1_GET_OPERATION_MODE_2FA) {
  buffer[0] = SFA_NFC;
 }
 apdu.setOutgoingAndSend((short)0, (short)1);
}
 
Example 9
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 5 votes vote down vote up
/**
 * CHANGE REFERENCE DATA APDU implementation.
 */
private void changeReferenceData(APDU apdu) {
  byte buffer[] = apdu.getBuffer();
  if (buffer[ISO7816.OFFSET_P1] != (byte) 0) {
    ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
  }
  byte pinOffset = PIN_INDEX_PW1;
  byte minLength = MIN_PIN1_LENGTH;
  byte type = buffer[ISO7816.OFFSET_P2];
  if (type == (byte) 0x83) {
    pinOffset = PIN_INDEX_PW3;
    minLength = MIN_PIN3_LENGTH;
  } else if (type != (byte) 0x81) {
    ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
  }
  byte currentLength = pinLength[pinOffset];
  short length = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
  if (apdu.setIncomingAndReceive() != length ||
      length > currentLength + MAX_PIN_LENGTH ||
      length < currentLength + minLength) {
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  }
  if (pins[pinOffset].getTriesRemaining() == 0) {
    ISOException.throwIt(SW_PIN_BLOCKED);
  }
  if (!pins[pinOffset].check(buffer, ISO7816.OFFSET_CDATA, currentLength)) {
    pinSubmitted[0] = false;
    ISOException.throwIt((short) (SW_PIN_FAILED_00 + pins[pinOffset].getTriesRemaining()));
  }
  updatePIN(pinOffset, buffer, (short) (ISO7816.OFFSET_CDATA + currentLength),
            (byte) (length - currentLength));
}
 
Example 10
Source File: OCUnitTests.java    From JCMathLib with MIT License 5 votes vote down vote up
void test_BN_MUL(APDU apdu, short dataLen, boolean bFastEngine) {
    byte[] apdubuf = apdu.getBuffer();
    short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);

    PM.check(PM.TRAP_BN_MUL_1);    
    Bignat mul1 = m_testBN1;
    mul1.set_size(p1);
    PM.check(PM.TRAP_BN_MUL_2);
    Bignat mul2 = m_testBN2;
    mul2.set_size((short) (dataLen - p1));
    PM.check(PM.TRAP_BN_MUL_3);
    Bignat product = m_testBN3;
    product.set_size(dataLen);
    PM.check(PM.TRAP_BN_MUL_4);
    mul1.from_byte_array(p1, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
    mul2.from_byte_array((short)(dataLen-p1), (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
    PM.check(PM.TRAP_BN_MUL_5);
    if (bFastEngine && !bIsSimulator) {
        product.mult_rsa_trick(mul1, mul2, null, null);
    }
    else {
        product.mult_schoolbook(mul1, mul2);        
    }
    PM.check(PM.TRAP_BN_MUL_6);
    short len = product.copy_to_buffer(apdubuf, (short) 0);
    apdu.setOutgoingAndSend((short) 0, len);
}
 
Example 11
Source File: OCUnitTests.java    From JCMathLib with MIT License 5 votes vote down vote up
void test_EC_COMPARE(APDU apdu) {
    byte[] apdubuf = apdu.getBuffer();
    short p1_len = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
    short p2_len = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
    
    m_testPoint1.setW(apdubuf, (short) ISO7816.OFFSET_CDATA, p1_len);
    m_testPoint2.setW(apdubuf, (short) (ISO7816.OFFSET_CDATA + p1_len), p2_len);
    apdubuf[0] = 0; apdubuf[1] = 0; apdubuf[2] = 0; apdubuf[3] = 0; // Tests expects big integer
    apdubuf[4] = m_testPoint1.isEqual(m_testPoint2) ? (byte) 1 : (byte) 0;
    apdu.setOutgoingAndSend((short) 0, (short) 5);
}
 
Example 12
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 5 votes vote down vote up
/** 
 * This function creates a PIN with parameters specified by the P1, P2 and DATA
 * values. P2 specifies the maximum number of consecutive unsuccessful
 * verifications before the PIN blocks. PIN can be created only if one of the logged identities
 * allows it. 
 * 
 * ins: 0x40
 * p1: PIN number (0x00-0x07)
 * p2: max attempt number
 * data: [PIN_size(1b) | PIN | UBLK_size(1b) | UBLK] 
 * return: none
 */
private short CreatePIN(APDU apdu, byte[] buffer) {
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	
	byte pin_nb = buffer[ISO7816.OFFSET_P1];
	byte num_tries = buffer[ISO7816.OFFSET_P2];
	
	if ((pin_nb < 0) || (pin_nb >= MAX_NUM_PINS) || (pins[pin_nb] != null))
		ISOException.throwIt(SW_INCORRECT_P1);
	/* Allow pin lengths > 127 (useful at all ?) */
	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
	// At least 1 character for PIN and 1 for unblock code (+ lengths)
	if (bytesLeft < 4)
		ISOException.throwIt(SW_INVALID_PARAMETER);
	byte pin_size = buffer[ISO7816.OFFSET_CDATA];
	if (bytesLeft < (short) (1 + pin_size + 1))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	if (!CheckPINPolicy(buffer, (short) (ISO7816.OFFSET_CDATA + 1), pin_size))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	byte ucode_size = buffer[(short) (ISO7816.OFFSET_CDATA + 1 + pin_size)];
	if (bytesLeft != (short) (1 + pin_size + 1 + ucode_size))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	if (!CheckPINPolicy(buffer, (short) (ISO7816.OFFSET_CDATA + 1 + pin_size + 1), ucode_size))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	pins[pin_nb] = new OwnerPIN(num_tries, PIN_MAX_SIZE);
	pins[pin_nb].update(buffer, (short) (ISO7816.OFFSET_CDATA + 1), pin_size);
	ublk_pins[pin_nb] = new OwnerPIN((byte) 3, PIN_MAX_SIZE);
	// Recycle variable pin_size
	pin_size = (byte) (ISO7816.OFFSET_CDATA + 1 + pin_size + 1);
	ublk_pins[pin_nb].update(buffer, pin_size, ucode_size);
	
	return (short)0;
}
 
Example 13
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 14
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
   * This function signs the current hash transaction with a std or the last extended key
   * The hash provided in the APDU is compared to the version stored inside the chip.
* Depending of the total amount in the transaction and the predefined limit, 
* a HMAC must be provided as an additional security layer. 
* 
   * ins: 0x6F
* 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 SignTransaction(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 doublehash value in buffer with cached singlehash value
sha256.reset();
sha256.doFinal(transactionData, OFFSET_TRANSACTION_HASH, MessageDigest.LENGTH_SHA_256, recvBuffer, (short)0);
if ((byte)0 != Util.arrayCompare(buffer, ISO7816.OFFSET_CDATA, recvBuffer, (short)0, MessageDigest.LENGTH_SHA_256))
	ISOException.throwIt(SW_INCORRECT_TXHASH);

// check challenge-response answer if necessary
if(needs_2FA){
	if(	Biginteger.lessThan(data2FA, OFFSET_2FA_LIMIT, transactionData, OFFSET_TRANSACTION_AMOUNT, (short)8)){
		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: (doublesha256(raw_tx) | 32bytes zero-padding)
		Util.arrayFillNonAtomic(recvBuffer, (short)32, (short)32, (byte)0x00);
		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);
		// reset total amount
		Util.arrayFillNonAtomic(transactionData, OFFSET_TRANSACTION_TOTAL, (short)8, (byte)0x00);
	}
	else{					
		//update total amount
		Util.arrayCopyNonAtomic(transactionData, OFFSET_TRANSACTION_AMOUNT, transactionData, OFFSET_TRANSACTION_TOTAL, (short)8);
	}
}

// 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.sign(transactionData, OFFSET_TRANSACTION_HASH, (short)32, buffer, (short)0);
      return sign_size;
  }
 
Example 15
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/** 
 * This function returns the public key associated with a particular private key stored 
 * in the applet. The exact key blob contents depend on the key�s algorithm and type. 
 * 
 * ins: 0x35
 * p1: private key number (0x00-0x0F)
 * p2: 0x00
 * data: none 
 * return(SECP256K1): [coordx_size(2b) | pubkey_coordx | sig_size(2b) | sig]
 */
private short getPublicKeyFromPrivate(APDU apdu, byte[] buffer) {
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	
	if (buffer[ISO7816.OFFSET_P2] != (byte) 0x00)
		ISOException.throwIt(SW_INCORRECT_P2);
	
	byte key_nb = buffer[ISO7816.OFFSET_P1];
	if ((key_nb < 0) || (key_nb >= MAX_NUM_KEYS))
		ISOException.throwIt(SW_INCORRECT_P1);
	
	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);
	// check the curve param
	if(!Secp256k1.checkCurveParameters((ECPrivateKey)key, recvBuffer, (short)0))
		ISOException.throwIt(SW_INCORRECT_ALG);
			
	// compute the corresponding partial public key...
       keyAgreement.init((ECPrivateKey)key);
       short coordx_size=(short)32;
   	keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, buffer, (short)1); //pubkey in uncompressed form
    Util.setShort(buffer, (short)0, coordx_size);
       
       // sign fixed message
       sigECDSA.init(key, Signature.MODE_SIGN);
       short sign_size= sigECDSA.sign(buffer, (short)0, (short)(coordx_size+2), buffer, (short)(coordx_size+4));
       Util.setShort(buffer, (short)(coordx_size+2), sign_size);
       
       // return x-coordinate of public key+signature
       // the client can recover full public-key from the signature or
       // by guessing the compression value () and verifying the signature... 
       return (short)(2+coordx_size+2+sign_size);
}
 
Example 16
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/** 
 * This function allows to reset a private ECkey stored in the card.
 * If 2FA is enabled, a hmac code must be provided to reset the key.
 * 
 * ins: 0x33
 * p1: private key number (0x00-0x0F)
 * p2: 0x00
 * data: [ (option)HMAC-2FA(20b)] 
 * return: none
 */
private short ResetKey(APDU apdu, byte[] buffer) {
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	
	if (buffer[ISO7816.OFFSET_P2] != (byte) 0x00)
		ISOException.throwIt(SW_INCORRECT_P2);
	byte key_nb = buffer[ISO7816.OFFSET_P1];
	if ((key_nb < 0) || (key_nb >= MAX_NUM_KEYS))
		ISOException.throwIt(SW_INCORRECT_P1);
	
	Key key = eckeys[key_nb];
	// check type and size
	if ((key == null) || !key.isInitialized())
		ISOException.throwIt(SW_INCORRECT_P1);
	
	// check 2FA if required
	if (needs_2FA){
		short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
		
		if (bytesLeft < (short)20)
			ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
		
		// compute the corresponding partial public key...
		keyAgreement.init((ECPrivateKey)key);
		keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, tmpBuffer, (short)0); //pubkey in uncompressed form
		Util.arrayCopy(tmpBuffer, (short)1, recvBuffer, (short)0, (short)32);
		// hmac of 64-bytes msg: (pubkey-x | 32bytes (0x20^key_nb)-padding)
		Util.arrayFillNonAtomic(recvBuffer, (short)32, (short)32, (byte) (0x20^key_nb));
		HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, recvBuffer, (short)0, (short)64, recvBuffer, (short)64);
		if (Util.arrayCompare(buffer, ISO7816.OFFSET_CDATA, recvBuffer, (short)64, (short)20)!=0)
			ISOException.throwIt(SW_SIGNATURE_INVALID);			
	}
	
	// clear key & reset flag
	key.clearKey();
	eckeys_flag &= (short) ~(0x0001 << key_nb);// reset corresponding bit flag;
	
	return (short)0;
}
 
Example 17
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 18
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 19
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 20
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/** 
 * This function changes a PIN code. The DATA portion contains both the old and
 * the new PIN codes. 
 * 
 * ins: 0x44
 * p1: PIN number (0x00-0x07)
 * p2: 0x00
 * data: [PIN_size(1b) | old_PIN | PIN_size(1b) | new_PIN ] 
 * return: none (throws an exception in case of wrong PIN)
 */
private short ChangePIN(APDU apdu, byte[] buffer) {
	/*
	 * Here I suppose the PIN code is small enough that 2 of them enter in
	 * the buffer TODO: Verify the assumption and eventually adjust code to
	 * support reading PINs in multiple read()s
	 */
	byte pin_nb = buffer[ISO7816.OFFSET_P1];
	if ((pin_nb < 0) || (pin_nb >= MAX_NUM_PINS))
		ISOException.throwIt(SW_INCORRECT_P1);
	OwnerPIN pin = pins[pin_nb];
	if (pin == null)
		ISOException.throwIt(SW_INCORRECT_P1);
	if (buffer[ISO7816.OFFSET_P2] != (byte) 0x00)
		ISOException.throwIt(SW_INCORRECT_P2);
	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
	// At least 1 character for each PIN code
	if (bytesLeft < 4)
		ISOException.throwIt(SW_INVALID_PARAMETER);
	byte pin_size = buffer[ISO7816.OFFSET_CDATA];
	if (bytesLeft < (short) (1 + pin_size + 1))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	if (!CheckPINPolicy(buffer, (short) (ISO7816.OFFSET_CDATA + 1), pin_size))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	byte new_pin_size = buffer[(short) (ISO7816.OFFSET_CDATA + 1 + pin_size)];
	if (bytesLeft < (short) (1 + pin_size + 1 + new_pin_size))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	if (!CheckPINPolicy(buffer, (short) (ISO7816.OFFSET_CDATA + 1 + pin_size + 1), new_pin_size))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	
	byte triesRemaining	= pin.getTriesRemaining();
	if (triesRemaining == (byte) 0x00)
		ISOException.throwIt(SW_IDENTITY_BLOCKED);
	if (!pin.check(buffer, (short) (ISO7816.OFFSET_CDATA + 1), pin_size)) {
		LogoutIdentity(pin_nb);
		ISOException.throwIt((short)(SW_PIN_FAILED + triesRemaining - 1));
	}
	
	pin.update(buffer, (short) (ISO7816.OFFSET_CDATA + 1 + pin_size + 1), new_pin_size);
	// JC specifies this resets the validated flag. So we do.
	logged_ids &= (short) ((short) 0xFFFF ^ (0x01 << pin_nb));
	
	return (short)0;
}