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

The following examples show how to use javacard.framework.Util#makeShort() . 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: 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 3
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 5 votes vote down vote up
/** 
 * This function verifies a PIN number sent by the DATA portion. The length of
 * this PIN is specified by the value contained in P3.
 * Multiple consecutive unsuccessful PIN verifications will block the PIN. If a PIN
 * blocks, then an UnblockPIN command can be issued.
 * 
 * ins: 0x42
 * p1: PIN number (0x00-0x07)
 * p2: 0x00
 * data: [PIN] 
 * return: none (throws an exception in case of wrong PIN)
 */
private short VerifyPIN(APDU apdu, byte[] buffer) {
	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] != 0x00)
		ISOException.throwIt(SW_INCORRECT_P2);
	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
	/*
	 * Here I suppose the PIN code is small enough to enter in the buffer
	 * TODO: Verify the assumption and eventually adjust code to support
	 * reading PIN in multiple read()s
	 */
	if (!CheckPINPolicy(buffer, ISO7816.OFFSET_CDATA, (byte) bytesLeft))
		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, (byte) bytesLeft)) {
		LogoutIdentity(pin_nb);
		ISOException.throwIt((short)(SW_PIN_FAILED + triesRemaining - 1));
	}
	
	// Actually register that PIN has been successfully verified.
	logged_ids |= (short) (0x0001 << pin_nb);
	
	return (short)0;
}
 
Example 4
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 5 votes vote down vote up
/**
 * This function unblocks a PIN number using the unblock code specified in the
 * DATA portion. The P3 byte specifies the unblock code length. 
 * 
 * ins: 0x46
 * p1: PIN number (0x00-0x07)
 * p2: 0x00
 * data: [PUK] 
 * return: none (throws an exception in case of wrong PUK)
 */
private short UnblockPIN(APDU apdu, byte[] buffer) {
	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];
	OwnerPIN ublk_pin = ublk_pins[pin_nb];
	if (pin == null)
		ISOException.throwIt(SW_INCORRECT_P1);
	if (ublk_pin == null)
		ISOException.throwIt(SW_INTERNAL_ERROR);
	// If the PIN is not blocked, the call is inconsistent
	if (pin.getTriesRemaining() != 0)
		ISOException.throwIt(SW_OPERATION_NOT_ALLOWED);
	if (buffer[ISO7816.OFFSET_P2] != 0x00)
		ISOException.throwIt(SW_INCORRECT_P2);
	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
	/*
	 * Here I suppose the PIN code is small enough to fit into the buffer
	 * TODO: Verify the assumption and eventually adjust code to support
	 * reading PIN in multiple read()s
	 */
	if (!CheckPINPolicy(buffer, ISO7816.OFFSET_CDATA, (byte) bytesLeft))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	byte triesRemaining	= ublk_pin.getTriesRemaining();
	if (triesRemaining == (byte) 0x00)
		ISOException.throwIt(SW_IDENTITY_BLOCKED);
	if (!ublk_pin.check(buffer, ISO7816.OFFSET_CDATA, (byte) bytesLeft))
		ISOException.throwIt((short)(SW_PIN_FAILED + triesRemaining - 1));
	
	pin.resetAndUnblock();
	
	return (short)0;
}
 
Example 5
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 6
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 5 votes vote down vote up
/**
 * This function allows to reset the 2FA key and disable 2FA.
 * Once activated, 2FA can only be deactivated when the seed is reset and all eckeys cleared.
 *  
 *  ins: 0x78
 *  p1: 0x00
 *  p2: 0x00
 *  data: [hmacsha1_key(20b)]
 *  return: (none)
 */
private short reset2FAKey(APDU apdu, byte[] buffer){
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	
	// check length
	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
	if (bytesLeft < (short)20)
		ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
	
	// reset 2FA can only be done if all private keys are cleared
	if (!needs_2FA)
		ISOException.throwIt(SW_2FA_UNINITIALIZED_KEY);
	if (bip32_seeded)
		ISOException.throwIt(SW_BIP32_INITIALIZED_SEED);
	if (eckeys_flag != 0x0000)
		ISOException.throwIt(SW_ECKEYS_INITIALIZED_KEY);
	
	// compute hmac(2FA_ID) and compare with value provided 
	// hmac of 64-bytes msg: (id_2FA(20b) | 44 bytes 0xAA-padding)
	short offset= ISO7816.OFFSET_CDATA;
	Util.arrayFillNonAtomic(recvBuffer, (short)0, (short)64, (byte)0xAA);
	Util.arrayCopyNonAtomic(data2FA, OFFSET_2FA_ID, recvBuffer, (short)0, (short)20);
	HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, recvBuffer, (short)0, (short)64, recvBuffer, (short)64);
	if (Util.arrayCompare(buffer, offset, recvBuffer, (short)64, (short)20)!=0)
		ISOException.throwIt(SW_SIGNATURE_INVALID);
	
	// reset flag and data
       needs_2FA= false;	
       key_2FA.clearKey();
       Util.arrayFillNonAtomic(data2FA, (short)0, OFFSET_2FA_SIZE, (byte)0x00);      
       
       return (short)0;
}
 
Example 7
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 5 votes vote down vote up
/**
 * This function allows to set the 2FA key and enable 2FA.
 * Once activated, 2FA can only be deactivated when the seed is reset.
 *  
 *  ins: 0x79
 *  p1: 0x00
 *  p2: 0x00
 *  data: [hmacsha1_key(20b) | amount_limit(8b)]
 *  return: (none)
 */
private short set2FAKey(APDU apdu, byte[] buffer){
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	// cannot modify an existing 2FA!
	if (needs_2FA)
		ISOException.throwIt(SW_2FA_INITIALIZED_KEY);
	
	//check input length
	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
	if (bytesLeft < (short)(20+8))
		ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
	
	if (!done_once_2FA){
		data2FA= new byte[OFFSET_2FA_SIZE];
		randomData = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
        aes128_cbc= Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
        key_2FA= (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false);
        done_once_2FA= true;
	}
	
	short offset= ISO7816.OFFSET_CDATA;
	Util.arrayCopyNonAtomic(buffer, offset, data2FA, OFFSET_2FA_HMACKEY, (short)20); 
	offset+=(short)20;
	Util.arrayCopyNonAtomic(buffer, offset, data2FA, OFFSET_2FA_LIMIT, (short)8); 
	offset+=(short)8;
	// hmac derivation for id_2FA & key_2FA
	HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, CST_2FA, (short)0, (short)6, data2FA, OFFSET_2FA_ID);
       HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, CST_2FA, (short)6, (short)7, recvBuffer, (short)0);
       key_2FA.setKey(recvBuffer,(short)0); // AES-128: 16-bytes key!!
       needs_2FA= true;	
       
       return (short)0;
}
 
Example 8
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * This function resets the Bip32 seed and all derived keys: the master key, chain code, authentikey 
 * and the 32-bit AES key that is used to encrypt/decrypt Bip32 object stored in secure memory.
 * If 2FA is enabled, then a hmac code must be provided, based on the 4-byte counter-2FA.
 *  
 *  ins: 0x77
 *  p1: PIN_size 
 *  p2: 0x00
 *  data: [PIN | optional-hmac(20b)]
 *  return: (none)
 */
private short resetBIP32Seed(APDU apdu, byte[] buffer){
	
	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
	
	// check provided PIN
	byte pin_size= buffer[ISO7816.OFFSET_P1];
	OwnerPIN pin = pins[(byte)0x00];
	if (bytesLeft < pin_size)
		ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
	if (!CheckPINPolicy(buffer, ISO7816.OFFSET_CDATA, 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, (byte) pin_size)) {
		LogoutIdentity((byte)0x00);
		ISOException.throwIt((short)(SW_PIN_FAILED + triesRemaining - 1));
	}
	
	// check if seeded
	if (!bip32_seeded)
		ISOException.throwIt(SW_BIP32_UNINITIALIZED_SEED);
	
	// check 2FA if required
	if (needs_2FA){
		short offset= Util.makeShort((byte)0, ISO7816.OFFSET_CDATA);
		offset+=pin_size;
		bytesLeft-= pin_size;
		if (bytesLeft < (short)20)
			ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
		
		// compute hmac(counter_2FA) and compare with value provided 
		// hmac of 64-bytes msg: ( authentikey-coordx(32b) | 32bytes 0xFF-padding)
		Util.arrayFillNonAtomic(recvBuffer, (short)0, (short)64, (byte)0xFF);
		Util.arrayCopyNonAtomic(authentikey_pubkey, (short)0x01, recvBuffer, (short)0, BIP32_KEY_SIZE);
		HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, recvBuffer, (short)0, (short)64, recvBuffer, (short)64);
		if (Util.arrayCompare(buffer, offset, recvBuffer, (short)64, (short)20)!=0)
			ISOException.throwIt(SW_SIGNATURE_INVALID);
	}		
	// reset memory cache, bip32 flag and all data!
	bip32_om.reset();
	bip32_seeded= false;
	bip32_masterkey.clearKey(); 
	bip32_masterchaincode.clearKey();
	bip32_encryptkey.clearKey();
	bip32_authentikey.clearKey();
	Secp256k1.setCommonCurveParameters(bip32_authentikey);// keep public params!
	Util.arrayFillNonAtomic(authentikey_pubkey, (short)0, (short)(2*BIP32_KEY_SIZE+1), (byte)0x00);
	LogOutAll();
	return (short)0;
}
 
Example 9
Source File: LWNFCForumApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
@Override
public void process(APDU apdu) throws ISOException {
    if (selectingApplet()) {
        return;
    }
    byte[] buffer = apdu.getBuffer();
    if (buffer[ISO7816.OFFSET_CLA] != NFCFORUM_CLA) {
        ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
    }
    switch(buffer[ISO7816.OFFSET_INS]) {
        case INS_SELECT: {
            apdu.setIncomingAndReceive();
            short selectedFile = Util.getShort(buffer, ISO7816.OFFSET_CDATA);
            switch(selectedFile) {
                case EF_CONTAINER:
                    scratch[OFFSET_SELECTED_FILE] = SELECTED_FILE_CONTAINER;
                    break;
                case EF_NDEF:
                    scratch[OFFSET_SELECTED_FILE] = SELECTED_FILE_NDEF;
                    break;
                default:
                    ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
            }
        }
        break;
        
        case INS_READ: {
            short offset = Util.makeShort(buffer[ISO7816.OFFSET_P1], buffer[ISO7816.OFFSET_P2]);
            if (scratch[OFFSET_SELECTED_FILE] == SELECTED_FILE_NONE) {
                ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
            }
            byte[] fileData = null;
            switch(scratch[OFFSET_SELECTED_FILE]) {
                case SELECTED_FILE_CONTAINER:
                    fileData = CONTAINER_DATA;
                    break;
                case SELECTED_FILE_NDEF:
                    fileData = FILE_DATA;
                    break;
            }
            if (offset >= (short)fileData.length) {
                ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
            }
            short sizeRead = (short)(buffer[ISO7816.OFFSET_LC] & 0xff);
            short blockLength = (((short)(offset + sizeRead) > (short)fileData.length) ? (short)(fileData.length - offset) : sizeRead);
            Util.arrayCopyNonAtomic(fileData, offset, buffer, (short)0, blockLength);
            apdu.setOutgoingAndSend((short)0, blockLength);
        }
        break;
            
    }       
}
 
Example 10
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 11
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
	 * This function allows to initiate a Secure Channel
	 *  
	 *  ins: 0x81
	 *  p1: 0x00
	 *  p2: 0x00
	 *  data: [client-pubkey(65b)]
	 *  return: [coordx_size(2b) | authentikey-coordx | sig_size(2b) | self-sig | sig2_size(optional) | authentikey-sig(optional)]
	 */
	private short InitiateSecureChannel(APDU apdu, byte[] buffer){
		
		// get client pubkey
		short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
		if (bytesLeft < (short)65)
			ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
		if (buffer[ISO7816.OFFSET_CDATA] != (byte)0x04)
			ISOException.throwIt(SW_INVALID_PARAMETER);
			
		// generate a new ephemeral key
		sc_ephemeralkey.clearKey();
		Secp256k1.setCommonCurveParameters(sc_ephemeralkey);// keep public params!
		randomData.generateData(recvBuffer, (short)0, BIP32_KEY_SIZE);
		sc_ephemeralkey.setS(recvBuffer, (short)0, BIP32_KEY_SIZE); //random value first
		
		// compute the shared secret...
        keyAgreement.init(sc_ephemeralkey);        
        short coordx_size= (short)32;
    	keyAgreement.generateSecret(buffer, ISO7816.OFFSET_CDATA, (short) 65, recvBuffer, (short)0); //pubkey in uncompressed form
    	// derive sc_sessionkey & sc_mackey
    	HmacSha160.computeHmacSha160(recvBuffer, (short)1, (short)32, CST_SC, (short)6, (short)6, recvBuffer, (short)33);
        Util.arrayCopyNonAtomic(recvBuffer, (short)33, sc_buffer, OFFSET_SC_MACKEY, SIZE_SC_MACKEY);
        HmacSha160.computeHmacSha160(recvBuffer, (short)1, (short)32, CST_SC, (short)0, (short)6, recvBuffer, (short)33);
    	sc_sessionkey.setKey(recvBuffer,(short)33); // AES-128: 16-bytes key!!       
//    	//alternatively: derive session_key (sha256 of coordx)
//    	sha256.reset();
//    	sha256.doFinal(recvBuffer, (short)1, (short)32, recvBuffer, (short) 0);
//    	sc_sessionkey.setKey(recvBuffer,(short)0); // AES-128: 16-bytes key!!
//    	//derive mac_key
//    	sha256.reset();
//    	sha256.doFinal(recvBuffer, (short)0, (short)32, sc_mackey, (short) 0);
    	
    	//reset IV counter
    	Util.arrayFillNonAtomic(sc_buffer, OFFSET_SC_IV, SIZE_SC_IV, (byte) 0);
		
		// self signed ephemeral pubkey
		keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, buffer, (short)1); //pubkey in uncompressed form
		Util.setShort(buffer, (short)0, coordx_size);
		sigECDSA.init(sc_ephemeralkey, 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);
        
		// hash signed by authentikey if seed is initialized
        short offset= (short)(2+coordx_size+2+sign_size);
        if (bip32_seeded){
            sigECDSA.init(bip32_authentikey, Signature.MODE_SIGN);
            short sign2_size= sigECDSA.sign(buffer, (short)0, offset, buffer, (short)(offset+2));
            Util.setShort(buffer, offset, sign2_size);
            offset+=(short)(2+sign2_size); 
        }else{
        	Util.setShort(buffer, offset, (short)0);
        	offset+=(short)2;
        }
		
        initialized_secure_channel= true;
        
        // 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... 
        // buffer= [coordx_size(2) | coordx | sigsize(2) | sig | sig2_size(optional) | sig2(optional)]
        return offset;
	}
 
Example 12
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 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 imports a Bip32 seed to the applet and derives the master key and chain code.
 * It also derives a second ECC that uniquely authenticates the HDwallet: the authentikey.
 * Lastly, it derives a 32-bit AES key that is used to encrypt/decrypt Bip32 object stored in secure memory 
 * If the seed already exists, it is reset if the logged identities allow it.
 * 
 * The function returns the x-coordinate of the authentikey, self-signed.
 * The authentikey full public key can be recovered from the signature.
 *  
 *  ins: 0x6C
 *  p1: seed_size(1b) 
 *  p2: 0x00 
 *  data: [seed_data (seed_size)]
 *  return: [coordx_size(2b) | coordx | sig_size(2b) | sig]
 */
private short importBIP32Seed(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);
	// if already seeded, must call resetBIP32Seed first!
	if (bip32_seeded)
		ISOException.throwIt(SW_BIP32_INITIALIZED_SEED);
	
	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
	
	// get seed bytesize (max 64 bytes)
	byte bip32_seedsize = buffer[ISO7816.OFFSET_P1]; 
	if (bip32_seedsize <0 || bip32_seedsize>64)
		ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
	
	short offset= (short)ISO7816.OFFSET_CDATA;
	
	// derive master key!
	HmacSha512.computeHmacSha512(BITCOIN_SEED, (short)0, (short)BITCOIN_SEED.length, buffer, offset, (short)bip32_seedsize, recvBuffer, (short)0);
	bip32_masterkey.setKey(recvBuffer, (short)0); // data must be exactly 32 bytes long
	bip32_masterchaincode.setKey(recvBuffer, (short)32); // data must be exactly 32 bytes long
	
	// derive 2 more keys from seed:
	// - AES encryption key for secure storage of extended keys in object
	// - ECC key for authentication of sensitive data returned by the applet (hash, pubkeys)
	HmacSha512.computeHmacSha512(BITCOIN_SEED2, (short)0, (short)BITCOIN_SEED2.length, buffer, offset, (short)bip32_seedsize, recvBuffer, (short)64);
	bip32_authentikey.setS(recvBuffer, (short)64, BIP32_KEY_SIZE);
	bip32_encryptkey.setKey(recvBuffer, (short)96); // AES-128: 16-bytes key!!
	
	// bip32 is now seeded
	bip32_seeded= true;
	
	// clear recvBuffer
	Util.arrayFillNonAtomic(recvBuffer, (short)0, (short)128, (byte)0);
	
	// compute the partial authentikey public key...
       keyAgreement.init(bip32_authentikey);
       short coordx_size= (short)32;
   	keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, authentikey_pubkey, (short)0); //pubkey in uncompressed form
    Util.setShort(buffer, (short)0, coordx_size);
       Util.arrayCopyNonAtomic(authentikey_pubkey, (short)1, buffer, (short)2, coordx_size);
       // self signed public key
       sigECDSA.init(bip32_authentikey, Signature.MODE_SIGN);
       short sign_size= sigECDSA.sign(buffer, (short)0, (short)(coordx_size+2), buffer, (short)(coordx_size+4));
       Util.setShort(buffer, (short)(2+coordx_size), 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... 
       // buffer= [coordx_size(2) | coordx | sigsize(2) | sig]
       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 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;
}
 
Example 17
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 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;
}