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

The following examples show how to use javacard.framework.Util#arrayCopyNonAtomic() . 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: Records.java    From CardExamples with The Unlicense 6 votes vote down vote up
/**
 * Constructor for SFI Record object.
 * 
 * @param sfi
 * @param recordNumber
 * @param data
 * @param dataOffset
 * @param dataLength
 */
private Record(byte sfi, byte recordNumber, byte[] data, short dataOffset, short dataLength) {
    this.sfi = sfi;
    this.recordNumber = recordNumber;

    // Add tag and length to record data.
    short recordLength = (short) (dataLength + (byte) 2);
    if (dataLength > (short) 127) {
        recordLength++;
    }
    this.data = new byte[recordLength];
    // Reuse 'recordLength' to track offset.
    recordLength = (short) 0;
    this.data[recordLength++] = Constants.TAG_READ_RECORD_RESPONSE_MESSAGE_TEMPLATE;
    if (dataLength > (short) 127) {
        this.data[recordLength++] = (byte) 0x81;
    }
    this.data[recordLength++] = (byte) dataLength;
    this.dataLength = Util.arrayCopyNonAtomic(data, dataOffset, this.data, recordLength, dataLength);
}
 
Example 2
Source File: Bip32ObjectManager.java    From SatochipApplet with GNU Affero General Public License v3.0 6 votes vote down vote up
/**
 * Creates an object by reserving a fixed memory size for it.
 * Throws a SW_NO_MEMORY_LEFT exception if cannot allocate the memory.
 * 
 * @param src
 *            the source array to copy from
 * @param srcOff
 *            the offset for the source array
 *            
 * @return The memory base address for the object.
 */
public short createObject(byte[] src, short srcOff) {
	if (nb_elem_free == 0)
		ISOException.throwIt(SW_NO_MEMORY_LEFT);		
	
	short base=0;
	while (base<this.size) {
		if (Util.arrayCompare(this.ptr, base, this.empty, (short)0, this.size_id)==0){
			Util.arrayCopyNonAtomic(src, srcOff, this.ptr, base, this.size_elem);
			this.nb_elem_free--;
			this.nb_elem_used++;
			return base;
		}
		base+=this.size_elem;	
	}
	return NULL_OFFSET;//should not happen
}
 
Example 3
Source File: ECPoint.java    From JCMathLib with MIT License 5 votes vote down vote up
/**
 * Returns the Y coordinate of this point in uncompressed form.
 *
 * @param buffer output array for Y coordinate
 * @param offset start offset within output array
 * @return length of Y coordinate (in bytes)
 */    
public short getY(byte[] buffer, short offset) {
    ech.lock(ech.uncompressed_point_arr1);
    thePoint.getW(ech.uncompressed_point_arr1, (short) 0);
    Util.arrayCopyNonAtomic(ech.uncompressed_point_arr1, (short)(1 + this.theCurve.COORD_SIZE), buffer, offset, this.theCurve.COORD_SIZE);
    ech.unlock(ech.uncompressed_point_arr1);
    return this.theCurve.COORD_SIZE;
}
 
Example 4
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 5 votes vote down vote up
private static void handleGetHalfPublicKey(APDU apdu) throws ISOException {
 byte[] buffer = apdu.getBuffer();
 apdu.setIncomingAndReceive();
 short offset = ISO7816.OFFSET_CDATA;
 byte derivationSize = buffer[offset++];
 byte i;
 if (Crypto.keyAgreement == null) {
  ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
 }
 if (derivationSize > MAX_DERIVATION_PATH) {
  ISOException.throwIt(ISO7816.SW_DATA_INVALID);
 }
    Crypto.initCipher(chipKey, false);
    Crypto.blobEncryptDecrypt.doFinal(masterDerived, (short)0, (short)DEFAULT_SEED_LENGTH, scratch256, (short)0);
    i = Bip32Cache.copyPrivateBest(buffer, (short)(ISO7816.OFFSET_CDATA + 1), derivationSize, scratch256, (short)0);
    for (; i<derivationSize; i++) {
     Util.arrayCopyNonAtomic(buffer, (short)(offset + 4 * i), scratch256, Bip32.OFFSET_DERIVATION_INDEX, (short)4);
     if ((proprietaryAPI == null) && ((scratch256[Bip32.OFFSET_DERIVATION_INDEX] & (byte)0x80) == 0)) {
      if (!Bip32Cache.setPublicIndex(buffer, (short)(ISO7816.OFFSET_CDATA + 1), i)) {
       ISOException.throwIt(SW_PUBLIC_POINT_NOT_AVAILABLE);
      }
     }
     if (!Bip32.derive(buffer)) {
      ISOException.throwIt(ISO7816.SW_WRONG_DATA);
     }
     Bip32Cache.storePrivate(buffer, (short)(ISO7816.OFFSET_CDATA + 1), (byte)(i + 1), scratch256);
    }
    Crypto.initTransientPrivate(scratch256, (short)0);
    Crypto.keyAgreement.init(Crypto.transientPrivate);
    Crypto.keyAgreement.generateSecret(Secp256k1.SECP256K1_G, (short)0, (short)Secp256k1.SECP256K1_G.length, scratch256, (short)32);
    offset = 0;
    Crypto.random.generateData(buffer, (short)offset, (short)32);
    offset += 32;
    Util.arrayCopyNonAtomic(scratch256, (short)32, buffer, offset, (short)32);
    offset += 32;
    signTransientPrivate(scratch256, (short)0, buffer, (short)0, buffer, offset);
    offset += buffer[(short)(offset + 1)] + 2;
    Crypto.digestScratch.doFinal(buffer, (short)0, (short)32, buffer, (short)0);
    apdu.setOutgoingAndSend((short)0, offset);
}
 
Example 5
Source File: FIDOCCImplementation.java    From CCU2F with Apache License 2.0 5 votes vote down vote up
private short computeHmacSha256(byte[] key, short key_offset, short key_length, 
	byte[] message, short message_offset, short message_length,
	byte[] mac, short mac_offset){
  	
  	byte[] hmacBuffer = JCSystem.makeTransientByteArray((short) 128, JCSystem.CLEAR_ON_DESELECT);

  	short BLOCKSIZE=64; 
  	short HASHSIZE=32;
  	
// compute inner hash
for (short i=0; i<key_length; i++){
	hmacBuffer[i]= (byte) (key[(short)(key_offset+i)] ^ (0x36));
}
Util.arrayFillNonAtomic(hmacBuffer, key_length, (short)(BLOCKSIZE-key_length), (byte)0);		
Util.arrayCopyNonAtomic(message, message_offset, hmacBuffer, BLOCKSIZE, message_length);
sha256.reset();
sha256.doFinal(hmacBuffer, (short)0, (short)(BLOCKSIZE+message_length), hmacBuffer, BLOCKSIZE); // copy hash result to data buffer!

// compute outer hash
for (short i=0; i<key_length; i++){
	hmacBuffer[i]= (byte) (key[(short)(key_offset+i)] ^ (0x5c));
}
Util.arrayFillNonAtomic(hmacBuffer, key_length, (short)(BLOCKSIZE-key_length), (byte)0);
// previous hash already copied to correct offset in scratch
sha256.reset();
sha256.doFinal(hmacBuffer, (short)0, (short)(BLOCKSIZE+HASHSIZE), mac, mac_offset);

return HASHSIZE;
  }
 
Example 6
Source File: Bignat.java    From JCMathLib with MIT License 5 votes vote down vote up
/**
 * Shifts stored value to right by specified number of bytes. This operation equals to multiplication by value numBytes * 256.
 * @param numBytes number of bytes to shift
 */
public void shift_bytes_right(short numBytes) {
    // Move whole content by numBytes offset
    bnh.lock(bnh.fnc_shift_bytes_right_tmp);
    Util.arrayCopyNonAtomic(this.value, (short) 0, bnh.fnc_shift_bytes_right_tmp, (short) 0, (short) (this.value.length));
    Util.arrayCopyNonAtomic(bnh.fnc_shift_bytes_right_tmp, (short) 0, this.value, numBytes, (short) ((short) (this.value.length) - numBytes));
    Util.arrayFillNonAtomic(this.value, (short) 0, numBytes, (byte) 0);
    bnh.unlock(bnh.fnc_shift_bytes_right_tmp);
}
 
Example 7
Source File: PasswordManagerApplet.java    From sim-password-manager with Apache License 2.0 5 votes vote down vote up
private void initAes() {
    Util.arrayCopyNonAtomic(iv, OFFSET_ZERO, cbcV, OFFSET_ZERO,
            (short) iv.length);
    Util.arrayFillNonAtomic(cbcNextV, OFFSET_ZERO, (short) cbcNextV.length,
            (byte) 0);
    Util.arrayFillNonAtomic(roundKeysBuff, OFFSET_ZERO,
            (short) roundKeysBuff.length, (byte) 0);
}
 
Example 8
Source File: Records.java    From CardExamples with The Unlicense 5 votes vote down vote up
/**
 * Find record, retrieve record data, return record data.
 * 
 * @param sfi
 * @param recordNumber
 * @param dataBuffer
 * @return
 */
short getRecordData(byte sfi, short recordNumber, byte[] dataBuffer) {
    byte result = findSFIRecord(sfi, recordNumber);
    if (result == RECORD_FOUND) {
        return Util.arrayCopyNonAtomic(this.foundRecord.data, (short) 0, dataBuffer, (short) 0, this.foundRecord.dataLength);
    }

    // Use offset 1 to indicate error type.
    dataBuffer[(byte) 1] = result;

    // Record not found.
    // dataBuffer[1] = 0x00 if SFI not found.
    //                 0x01 if SFI found, record number not found.
    return (short) -1;
}
 
Example 9
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 10
Source File: Bignat.java    From JCMathLib with MIT License 4 votes vote down vote up
/**
 * One digit left shift.
 * <P>
 * Asserts that the first digit is zero.
 */
public void shift_left() {
    // NOTE: assumes that overlapping src and dest arrays are properly handled by Util.arrayCopyNonAtomic
    Util.arrayCopyNonAtomic(this.value, (short) 1, this.value, (short) 0, (short) (size - 1)); 
    value[(short) (size - 1)] = 0;
}
 
Example 11
Source File: Bip32.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
public static boolean derive(byte[] apduBuffer) {
	boolean isZero = true;
	byte i;
	if ((LedgerWalletApplet.scratch256[OFFSET_DERIVATION_INDEX] & (byte)0x80) == 0) {
		if (LedgerWalletApplet.proprietaryAPI != null) {
			LedgerWalletApplet.proprietaryAPI.getUncompressedPublicPoint(LedgerWalletApplet.scratch256, (short)0, LedgerWalletApplet.scratch256, OFFSET_TMP);				
		}
		else {				
			if (!Bip32Cache.copyLastPublic(LedgerWalletApplet.scratch256, OFFSET_TMP)) {
				return false;
			}
		}
		AddressUtils.compressPublicKey(LedgerWalletApplet.scratch256, OFFSET_TMP);
	}
	else {
		LedgerWalletApplet.scratch256[OFFSET_TMP] = 0;
		Util.arrayCopyNonAtomic(LedgerWalletApplet.scratch256, (short)0, LedgerWalletApplet.scratch256, (short)(OFFSET_TMP + 1), (short)32);
	}
	Util.arrayCopyNonAtomic(LedgerWalletApplet.scratch256, OFFSET_DERIVATION_INDEX, LedgerWalletApplet.scratch256, (short)(OFFSET_TMP + 33), (short)4);
	if (Crypto.signatureHmac != null) {
		Crypto.keyHmac.setKey(LedgerWalletApplet.scratch256, (short)32, (short)32);
		if ((LedgerWalletApplet.proprietaryAPI != null) && (LedgerWalletApplet.proprietaryAPI.hasHmacSHA512())) {
			LedgerWalletApplet.proprietaryAPI.hmacSHA512(Crypto.keyHmac, LedgerWalletApplet.scratch256, OFFSET_TMP, (short)37, LedgerWalletApplet.scratch256, OFFSET_TMP);
		}
		else {
			Crypto.signatureHmac.init(Crypto.keyHmac, Signature.MODE_SIGN);
			Crypto.signatureHmac.sign(LedgerWalletApplet.scratch256, OFFSET_TMP, (short)37, LedgerWalletApplet.scratch256, OFFSET_TMP);
		}
	}
	else {
		HmacSha512.hmac(LedgerWalletApplet.scratch256, (short)32, (short)32, LedgerWalletApplet.scratch256, OFFSET_TMP, (short)37, LedgerWalletApplet.scratch256, OFFSET_TMP, apduBuffer, OFFSET_BLOCK);
	}
	if (MathMod256.ucmp(LedgerWalletApplet.scratch256, OFFSET_TMP, Secp256k1.SECP256K1_R, (short)0) >= 0) {
		return false;
	}
	MathMod256.addm(LedgerWalletApplet.scratch256, (short)0, LedgerWalletApplet.scratch256, OFFSET_TMP, LedgerWalletApplet.scratch256, (short)0, Secp256k1.SECP256K1_R, (short)0);
	for (i=0; i<(byte)32; i++) {
		if (LedgerWalletApplet.scratch256[i] != 0) {
			isZero = false;
			break;
		}
	}
	if (isZero) {
		return false;
	}
	Util.arrayCopyNonAtomic(LedgerWalletApplet.scratch256, (short)(OFFSET_TMP + 32), LedgerWalletApplet.scratch256, (short)32, (short)32);		
	return true;
}
 
Example 12
Source File: Keycard.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
public static void setPairingData(byte[] data, short offset) {
    pairingData[0] = (byte)0x01;
    Util.arrayCopyNonAtomic(data, offset, pairingData, (short)1, PAIRING_DATA_SIZE);
}
 
Example 13
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
private static void handleSignMessage(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    short offset = ISO7816.OFFSET_CDATA;
    if (buffer[ISO7816.OFFSET_P1] == P1_PREPARE_MESSAGE) {
        byte derivationSize = buffer[offset++];
        boolean addressVerified = false;
        if (Util.arrayCompare(buffer, offset, SLIP13_HEAD, (short)0, (short)SLIP13_HEAD.length) == (short)0) {
            addressVerified = true;
        }
        else {
            for (byte i=0; i<derivationSize; i++) {
                if ((Util.arrayCompare(buffer, (short)(offset + 2), BITID_DERIVE, (short)0, (short)BITID_DERIVE.length) == (short)0) ||
                    (Util.arrayCompare(buffer, (short)(offset + 2), BITID_DERIVE_MULTIPLE, (short)0, (short)BITID_DERIVE_MULTIPLE.length) == (short)0)) {
                    addressVerified = true;
                    break;
                }
                offset += 4;
            }
        }
        if (!addressVerified) {
            ISOException.throwIt(ISO7816.SW_WRONG_DATA);
        }
        offset = (short)(ISO7816.OFFSET_CDATA + 1 + 4 * derivationSize);
        short messageLength = (short)(buffer[offset++] & 0xff);
        Crypto.digestFull.reset();
        Crypto.digestFull.update(SIGNMAGIC, (short)0, (short)SIGNMAGIC.length);
        scratch256[(short)100] = (byte)messageLength;
        Crypto.digestFull.update(scratch256, (short)100, (short)1);
        Crypto.digestFull.doFinal(buffer, offset, messageLength, scratch256, (short)32);
        signTransientPrivate(scratch256, (short)0, scratch256, (short)32, scratch256, (short)100);
        Util.arrayFillNonAtomic(scratch256, (short)0, (short)64, (byte)0x00);
        buffer[(short)0] = (byte)0x00;
        TC.ctx[TC.TX_B_MESSAGE_SIGN_READY] = (byte)0x01;
        apdu.setOutgoingAndSend((short)0, (short)1);
    }
    else
    if (buffer[ISO7816.OFFSET_P1] == P1_SIGN_MESSAGE) {
        if (TC.ctx[TC.TX_B_MESSAGE_SIGN_READY] != (byte)0x01) {
            ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
        }
        TC.ctx[TC.TX_B_MESSAGE_SIGN_READY] = (byte)0x00;
        short signatureSize = (short)((short)(scratch256[(short)101] & 0xff) + 2);
        Util.arrayCopyNonAtomic(scratch256, (short)100, buffer, (short)0, signatureSize);
        apdu.setOutgoingAndSend((short)0, signatureSize);
    }
    else {
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }
}
 
Example 14
Source File: JavaCardAES.java    From sim-password-manager with Apache License 2.0 4 votes vote down vote up
/**
 * Sechedule AES round keys fro given key material
 * @param key ... key array
 * @param keyOffset ... start offset in key array
 * @param aesRoundKeys ... array to hold scheduled keys
 */
public void RoundKeysSchedule(byte key[], short keyOffset, byte aesRoundKeys[]) {
  byte     i;
  byte     j;
  byte     round;
  byte     rconpointer = 0;
  short    sourceOffset = 0;
  short    targetOffset = 0;
  // hlp CONTAINS PRECALCULATED EXPRESSION (round * (4 * KEYN))
  short    hlp = 0;

  // FIRST KEY (SAME AS INPUT KEY)
  Util.arrayCopyNonAtomic(key, keyOffset, aesRoundKeys, (short) 0, STATELEN);

  // 10 ROUNDS KEYS
  for (round = 1; round <= N_ROUNDS; round++) {
      // TIME REDUCING PRECALCULATION
      hlp += STATELEN;

      // COPY KEY FOR round - 1 TO BUFFER FOR round
      Util.arrayCopyNonAtomic(aesRoundKeys, (short) ((round - 1) * STATELEN), aesRoundKeys, hlp, STATELEN);

      rconpointer = (byte) (round - 1);

      for (i = 0; i < 4; i++) {
        sourceOffset = (short) ( ((i + 1) % 4) + ((KEYN-1) * 4) + hlp );
        targetOffset = (short) ( i + (0 * 4) + hlp );
        aesRoundKeys[targetOffset] ^= SBox[(aesRoundKeys[sourceOffset] >= 0) ? aesRoundKeys[sourceOffset] : (short) (256 + aesRoundKeys[sourceOffset])];
      }

      aesRoundKeys[hlp] ^= rcon[rconpointer];

      for (j = 1; j < KEYN; j++) {
          for (i = 0; i < 4; i++) {
            sourceOffset = (short) (i + ((j - 1) * 4) + hlp);
            targetOffset = (short) ((i + (j * 4)) + hlp);
            aesRoundKeys[targetOffset] ^= aesRoundKeys[sourceOffset];
          }
      }
  }
}
 
Example 15
Source File: Base58.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
public static short decode(byte[] in, short inOffset, short inLength, byte[] out, short outOffset, byte[] scratch, short scratchOffset) {
  try {  
    short zeroCount = (short)0, j, startAt;
    for (short i=0; i<inLength; i++) {
        short value = (short)(in[(short)(inOffset + i)] & 0xff);
        if (value > 128) {
            return (short)-1;
        }
        byte base58Value = BASE58TABLE[value];
        if (base58Value == (byte)0xff) {
            return (short)-1;
        }
        scratch[(short)(scratchOffset + i)] = base58Value;
    }
    while ((zeroCount < inLength) && (scratch[(short)(scratchOffset + zeroCount)] == 0)) {
        ++zeroCount;
    }
    j = inLength;
    startAt = zeroCount;
    while (startAt < inLength) {
        short remainder = 0;
        short divLoop;
        for (divLoop = startAt ; divLoop < inLength; divLoop++) {
            short digit256 = (short)(scratch[(short)(scratchOffset + divLoop)] & 0xff);
            short tmpDiv = (short)(remainder * 58 + digit256);
            scratch[(short)(scratchOffset + divLoop)] = (byte)(tmpDiv / 256);
            remainder = (short)(tmpDiv % 256);
        }
        if (scratch[(short)(scratchOffset + startAt)] == 0) {
            ++startAt;
        }
        out[(short)(outOffset + --j)] = (byte)remainder;
    }
    while ((j < inLength) && (out[(short)(outOffset + j)] == 0)) {
        j++;
    }
    short resultLength = (short)(inLength - (j - zeroCount));
    Util.arrayCopyNonAtomic(out, (short)(outOffset + j - zeroCount), out, outOffset, resultLength);
    return resultLength;
  }
  catch(Throwable t) {
      return (short)-1;
  }
}
 
Example 16
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
private static void handleTrustedInput(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    byte p1 = buffer[ISO7816.OFFSET_P1];
    byte dataOffset = (short)0;
    apdu.setIncomingAndReceive();
    if (p1 == P1_TRUSTED_INPUT_FIRST) {
        Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, TC.ctx, TC.TX_I_TRANSACTION_TARGET_INPUT, TC.SIZEOF_U32);
        TC.ctx[TC.TX_B_TRANSACTION_STATE] = Transaction.STATE_NONE;
        TC.ctx[TC.TX_B_TRUSTED_INPUT_PROCESSED] = (byte)0x00;
        TC.ctx[TC.TX_B_HASH_OPTION] = Transaction.HASH_FULL;
        dataOffset = (short)4;
    }
    else
    if (p1 != P1_TRUSTED_INPUT_NEXT) {
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }
    short remainingData = (short)((short)(buffer[ISO7816.OFFSET_LC] & 0xff) - dataOffset);
    byte result = Transaction.parseTransaction(Transaction.PARSE_TRUSTED_INPUT, buffer, (short)(ISO7816.OFFSET_CDATA + dataOffset), remainingData);
    if (result == Transaction.RESULT_ERROR) {
        ISOException.throwIt(ISO7816.SW_WRONG_DATA);
    }
    else
    if (result == Transaction.RESULT_MORE) {
        return;
    }
    else
    if (result == Transaction.RESULT_FINISHED) {
        short offset = 0;
        buffer[offset++] = BLOB_MAGIC_TRUSTED_INPUT;
        Crypto.random.generateData(buffer, offset, (short)3);
        offset += 3;
        Crypto.digestFull.doFinal(scratch256, (short)0, (short)0, scratch256, (short)0);
        Crypto.digestFull.doFinal(scratch256, (short)0, (short)32, buffer, offset);
        offset += 32;
        GenericBEHelper.swap(TC.SIZEOF_U32, buffer, offset, TC.ctx, TC.TX_I_TRANSACTION_TARGET_INPUT);
        offset += 4;
        Util.arrayCopyNonAtomic(TC.ctx, TC.TX_A_TRANSACTION_AMOUNT, buffer, offset, TC.SIZEOF_AMOUNT);
        offset += TC.SIZEOF_AMOUNT;
        Crypto.initCipher(trustedInputKey, true);
        Crypto.blobEncryptDecrypt.doFinal(buffer, (short)0, offset, scratch256, (short)0);
        Util.arrayCopyNonAtomic(scratch256, (short)(offset - 8), buffer, offset, (short)8);
        offset += 8;
        apdu.setOutgoingAndSend((short)0, offset);
    }
}
 
Example 17
Source File: TransitApplet.java    From JCMathLib with MIT License 4 votes vote down vote up
/**
 * Initializes a CAD/card interaction session. This is the first step of
 * mutual authentication. A new card challenge is generated and used along
 * with the passed-in host challenge to generate the derivation data from
 * which a new session key is derived. The card challenge is appended to the
 * response message. The response message is signed using the newly
 * generated session key then sent back. Note that mutual authentication is
 * subsequently completed upon succesful verification of the signature of
 * the first request received.
 * 
 * @param apdu
 *            The APDU
 */
private void initializeSession(APDU apdu) {

    // C-APDU: [CLA, INS, P1, P2, LC, [4-bytes Host Challenge]]

    byte[] buffer = apdu.getBuffer();

    if ((buffer[ISO7816.OFFSET_P1] != 0)
            || (buffer[ISO7816.OFFSET_P2] != 0)) {
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }

    byte numBytes = buffer[ISO7816.OFFSET_LC];

    byte count = (byte) apdu.setIncomingAndReceive();

    if (numBytes != CHALLENGE_LENGTH || count != CHALLENGE_LENGTH) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // Generate card challenge
    generateCardChallenge();

    // Generate key derivation data from host challenge and card challenge
    generateKeyDerivationData(buffer);

    // Generate session key from derivation data
    generateSessionKey();

    // R-APDU: [[4-bytes Card Challenge], [2-bytes Status Word], [8-bytes
    // MAC]]

    short offset = 0;

    // Append card challenge to response message
    offset = Util.arrayCopyNonAtomic(cardChallenge, (short) 0, buffer,
            offset, CHALLENGE_LENGTH);

    // Append status word to response message
    offset = Util.setShort(buffer, offset, SW_SUCCESS);

    // Sign response message and append MAC to response message
    offset = generateMAC(buffer, offset);

    // Send R-APDU
    apdu.setOutgoingAndSend((short) 0, offset);
}
 
Example 18
Source File: U2FApplet.java    From CCU2F with Apache License 2.0 4 votes vote down vote up
private void handleSign(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    short len = apdu.setIncomingAndReceive();
    short dataOffset = apdu.getOffsetCdata();
    byte p1 = buffer[ISO7816.OFFSET_P1];
    boolean sign = false;
    boolean counterOverflow = true;
    short keyHandleLength;
    boolean extendedLength = (dataOffset != ISO7816.OFFSET_CDATA);
    short outOffset = SCRATCH_PAD;
    if (len < 65) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    switch(p1) {
    case P1_SIGN_OPERATION:
        sign = true;
        break;
    case P1_SIGN_CHECK_ONLY:
        break;
    default:
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }
    // Check if the counter overflowed
    if (counterOverflowed) {
        ISOException.throwIt(ISO7816.SW_FILE_FULL);
    }
    // Verify key handle
    if (localPrivateTransient) {
        Secp256r1.setCommonCurveParameters(localPrivateKey);
    }
    keyHandleLength = (short)(buffer[(short)(dataOffset + 64)] & 0xff);
    if (!fidoImpl.unwrap(buffer, (short)(dataOffset + 65), keyHandleLength, buffer, (short)(dataOffset + APDU_APPLICATION_PARAMETER_OFFSET), (sign ? localPrivateKey : null))) {
        ISOException.throwIt(FIDO_SW_INVALID_KEY_HANDLE);
    }
    // If not signing, return with the "correct" exception
    if (!sign) {
        ISOException.throwIt(FIDO_SW_TEST_OF_PRESENCE_REQUIRED);
    }
    // If signing, only proceed if user presence can be validated
    if ((flags & INSTALL_FLAG_DISABLE_USER_PRESENCE) == 0) {
        if (scratchPersistent[0] != 0) {
            ISOException.throwIt(FIDO_SW_TEST_OF_PRESENCE_REQUIRED);
        }
    }
    scratchPersistent[0] = (byte)1;
    // Increase the counter
    boolean carry = false;
    JCSystem.beginTransaction();
    for (byte i=0; i<4; i++) {
        short addValue = (i == 0 ? (short)1 : (short)0);
        short val = (short)((short)(counter[(short)(4 - 1 - i)] & 0xff) + addValue);
        if (carry) {
            val++;
        }
        carry = (val > 255);
        counter[(short)(4 - 1 - i)] = (byte)val;
    }
    JCSystem.commitTransaction();
    if (carry) {
        // Game over
        counterOverflowed = true;
        ISOException.throwIt(ISO7816.SW_FILE_FULL);
    }
    // Prepare reply
    scratch[outOffset++] = FLAG_USER_PRESENCE_VERIFIED;
    outOffset = Util.arrayCopyNonAtomic(counter, (short)0, scratch, outOffset, (short)4);
    localSignature.init(localPrivateKey, Signature.MODE_SIGN);
    localSignature.update(buffer, (short)(dataOffset + APDU_APPLICATION_PARAMETER_OFFSET), (short)32);
    localSignature.update(scratch, SCRATCH_PAD, (short)5);
    outOffset += localSignature.sign(buffer, (short)(dataOffset + APDU_CHALLENGE_OFFSET), (short)32, scratch, outOffset);
  
    if (extendedLength) {
        // If using extended length, the message can be completed and sent immediately
        scratch[SCRATCH_TRANSPORT_STATE] = TRANSPORT_EXTENDED;
        Util.arrayCopyNonAtomic(scratch, SCRATCH_PAD, buffer, (short)0, outOffset);
        apdu.setOutgoingAndSend((short)0, (short)(outOffset - SCRATCH_PAD));
    }
    else {
        // Otherwise send the first chunk
        scratch[SCRATCH_TRANSPORT_STATE] = TRANSPORT_NOT_EXTENDED;
        Util.setShort(scratch, SCRATCH_CURRENT_OFFSET, (short)0);
        Util.setShort(scratch, SCRATCH_SIGNATURE_LENGTH, (short)0);
        Util.setShort(scratch, SCRATCH_NONCERT_LENGTH, (short)(outOffset - SCRATCH_PAD));
        Util.setShort(scratch, SCRATCH_FULL_LENGTH, (short)(outOffset - SCRATCH_PAD));
        scratch[SCRATCH_INCLUDE_CERT] = (byte)0;
        handleGetData(apdu);
    }
}
 
Example 19
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 20
Source File: Bignat.java    From JCMathLib with MIT License 2 votes vote down vote up
/**
 * Serialize this Bignat value into a provided buffer
 * @param buffer target buffer
 * @param bufferOffset start offset in buffer
 * @return number of bytes copied
 */
public short copy_to_buffer(byte[] buffer, short bufferOffset) {
    Util.arrayCopyNonAtomic(value, (short) 0, buffer, bufferOffset, size);
    return size;
}