/** * 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); }