/**
  * Generate an assymetric RSA key pair according to ISO7816-8, Section 5.1. We only support RSA
  * 1024 bit at the moment, and return data in simple TLV data objects, tags 81 and 82.
  *
  * <p>Successful MSE command has to be performed prior to this one.
  */
 private void processGenerateAssymetricKeyPair(APDU apdu) {
   // This is only valid in state initial (at the moment)
   if (state != STATE_INITIAL) {
     ISOException.throwIt(SW_INS_NOT_SUPPORTED);
   }
   byte[] buf = apdu.getBuffer();
   byte p1 = buf[OFFSET_P1];
   byte p2 = buf[OFFSET_P2];
   if (p1 != (byte) 0x80 || p2 != (byte) 0x00) {
     ISOException.throwIt(SW_INCORRECT_P1P2);
   }
   if (currentPrivateKey[0] == null) {
     ISOException.throwIt(SW_CONDITIONS_NOT_SATISFIED);
   }
   KeyPair pair = new KeyPair(tempKeyPublic, (RSAPrivateCrtKey) currentPrivateKey[0]);
   pair.genKeyPair();
   // Sanity check, the KeyPair class should regenerate the keys "in place".
   if (pair.getPrivate() != currentPrivateKey[0] || pair.getPublic() != tempKeyPublic) {
     ISOException.throwIt(SW_DATA_INVALID);
   }
   apdu.setOutgoing();
   short len = (short) 0;
   short offset = 0;
   buf[offset++] = (byte) 0x81;
   len = tempKeyPublic.getModulus(buf, (short) (offset + 2));
   buf[offset++] = (byte) 0x81;
   buf[offset++] = (byte) len;
   offset += len;
   buf[offset++] = (byte) 0x82;
   len = tempKeyPublic.getExponent(buf, (short) (offset + 1));
   buf[offset++] = (byte) len;
   offset += len;
   apdu.setOutgoingLength(offset);
   apdu.sendBytes((short) 0, offset);
 }
  public void process(APDU apdu) {
    // Good practice: Return 9000 on SELECT
    if (selectingApplet()) {
      return;
    }

    byte[] buff = apdu.getBuffer();
    // Get the incoming APDU
    // Util.arrayCopy(apdu.getBuffer(),(short) 0, buff,(short) 0,(short) apdu.getBuffer().length);//
    // apdu.getBuffer();
    // Check the CLA

    /*
    if(buff[ISO7816.OFFSET_CLA]!=CLA){
    	ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
    }
    */
    // Switch on the instruction code INS
    switch (buff[ISO7816.OFFSET_INS]) {
        //		Create a test signature using test
      case SEND_TEST_SIGNATURE:
        // Sign the test byte and get the signature size
        size = sig.sign(test, (short) 0, (short) test.length, output, (short) 0);
        break;
        //			return modulus of public key
      case SEND_PUB_MOD:
        // Retrieve the modulus, store it in the output byte array and set the output length
        size = k.getModulus(output, (short) 0);
        break;
        //		  return exponent of public key
      case SEND_PUB_EXP:
        //			Retrieve the public exponent, store it in the output byte array and set the output
        // length
        size = k.getExponent(output, (short) 0);
        break;
        //			return exponent of private key given correct pin authentication
      case SEND_PRV_EXP:
        // Check that the user is authenticated (correct command 0x80 0x03 0x01 0x00 0x04 0x00 0x00
        // 0x00 0x00 0x00)
        if (buff[ISO7816.OFFSET_P1] == ((byte) 0x01)) {
          if (buff[ISO7816.OFFSET_LC] != (byte) 0x00) {
            if (pin.check(buff, (short) (ISO7816.OFFSET_LC + 1), buff[ISO7816.OFFSET_LC])) {
              size = k2.getExponent(output, (short) 0);
              pin.reset();
            } else {
              // wrong pin (system should have taken care of decrementing the counter and checking
              // boundary conditions)
              ISOException.throwIt(ISO7816.SW_WRONG_DATA);
            }
          } else {
            ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); // no pin was sent
          }
        } else {
          ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); // wrong command code
        }
        //			Retrieve the private exponent, store it in the output byte array and set the output
        // length
        size = k2.getExponent(output, (short) 0);
        break;
        //			return size of signature and modulus for testing purposes (they should be the same)
      case (byte) SEND_KEY_LENGTH:
        shortToByteArray(keysize);
        size = (short) 2;
        Util.arrayCopy(buff, (short) 0, output, (short) 0, size);
        break;
        //			Sign arbitrary text sent to card
      case (byte) SIGN_INPUT_DATA:
        size = (short) buff[ISO7816.OFFSET_LC];
        size = sig.sign(buff, (short) (ISO7816.OFFSET_LC + 1), size, output, (short) 0);
        break;
        //			return the modulus of public keywith a random value sent from the host
      case (byte) SEND_AUTHENTICATED_PUB_EXP:
        // Find the size of the random value
        size = (short) buff[ISO7816.OFFSET_LC];
        // If the current key is 2048 bit =256 bytes we need a big array to store all data to sign
        // TODO limit the size of the input value and do some checks on it
        bigArray =
            JCSystem.makeTransientByteArray((short) (size + keysize), JCSystem.CLEAR_ON_RESET);
        // Update the signature object with that value
        Util.arrayCopy(buff, (short) (ISO7816.OFFSET_LC + 1), bigArray, (short) 0, size);
        k.getModulus(bigArray, (short) (size));
        // Util.arrayCopy(buff, (short) 0, bigArray, (short) (ISO7816.OFFSET_LC+size+1), len);
        size = sig.sign(bigArray, (short) 0, (short) bigArray.length, output, (short) 0);
        break;

      case (byte) 0x07:
        size = (short) 2;
        output[0] = (byte) 0x09;
        output[1] = (byte) 0x08;
        break;
      case (byte) 0x08:
        short length = 256;
        // short length = (short) buff.length;
        size = (short) length;
        // output[0]=(byte) 0x08;
        // output[1]=(byte) 0x08;

        for (short i = 0; i < length; i++) {
          output[i] = (byte) buff[i];
        }
        break;
      default:
        // good practice: If you don't know the INStruction, say so:
        ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
    }

    send(apdu);
  }