src/com/makina/security/OpenFIPS201/PIV.java
public short generateAsymmetricKeyPair(byte[] buffer, short offset, short length) {

        final byte CONST_TAG_TEMPLATE		= (byte)0xAC;
        final byte CONST_TAG_MECHANISM		= (byte)0x80;
        final byte CONST_TAG_PARAMETER 		= (byte)0x81;

        final short CONST_TAG_RESPONSE		= (short)0x7F49;
        final byte CONST_TAG_MODULUS		= (byte)0x81; // RSA - The modulus
        final byte CONST_TAG_EXPONENT		= (byte)0x82; // RSA - The public exponent

        //
        // PRE-CONDITIONS
        //

        // PRE-CONDITION 1 - The access rules must be satisfied for administrative access
        if (!cspPIV.checkAccessModeAdmin(false)) {
            ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
        }

        // PRE-CONDITION 2 - The 'TEMPLATE' tag must be present in the supplied buffer
        if (buffer[offset++] != CONST_TAG_TEMPLATE) {
            ISOException.throwIt(ISO7816.SW_WRONG_DATA);
        }

        // Skip the length byte
        offset++;

        // PRE-CONDITION 3 - The 'MECHANISM' tag must be present in the supplied buffer
        if (buffer[offset++] != CONST_TAG_MECHANISM) {
            ISOException.throwIt(ISO7816.SW_WRONG_DATA);
        }

        // PRE-CONDITION 4 - The 'MECHANISM' tag must have a length of 1
        if (buffer[offset++] != (short)1) {
            ISOException.throwIt(ISO7816.SW_WRONG_DATA);
        }

		// PRE-CONDITION 5 - The 'MECHANISM' tag value must be one of the supported mechanisms
		//if (buffer[offset] != PIV.ID_ALG_RSA_1024 && buffer[offset] != PIV.ID_ALG_RSA_2048) {
			//ISOException.throwIt(ISO7816.SW_WRONG_DATA);
		//}

        //
        // NOTE: We ignore the existence of the 'PARAMETER' tag, because according to SP800-78-4 the
        // RSA public exponent is now fixed to 65537 (Section 3.1 PIV Cryptographic Keys).
        // Since we don't support ECC algorithms yet, we have no other reason to read it.
        //

        // PRE-CONDITION 5 - The key reference and mechanism must point to an existing key
        PIVKeyObject key = cspPIV.selectKey(buffer[ISO7816.OFFSET_P2], buffer[offset]);
        if (key == null) {			
			// NOTE: The error message we return here is different dependant on whether the key is bad (6A86),
			// 		 or the mechanism is bad (6A80) (See SP800-73-4 3.3.2 Generate Asymmetric Keypair). 
			if (!cspPIV.keyExists(buffer[ISO7816.OFFSET_P2])) {
				// The key reference is bad
				ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
			} else {
				// The mechanism is bad
				ISOException.throwIt(ISO7816.SW_WRONG_DATA);			
			}
        }

        // PRE-CONDITION 6 - The key must be an assymetric key (key pair)
        if (!(key instanceof PIVKeyObjectPKI)) {
            ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
        }

        //
        // EXECUTION STEPS
        //

        // STEP 1 - Generate the key pair
        PIVKeyObjectPKI keyPair = (PIVKeyObjectPKI)key;
        keyPair.generate();

        // STEP 2 - Prepare the outgoing public key

        //
        // NOTE: We only support RSA keys in the current implementation so we're just direct casting.
        //		 Ideally we would use a factory to support multiple assymetric algorithms, but not today.
        //
        tlvWriter.init(scratch, (short)0, key.getKeyLength(), CONST_TAG_RESPONSE);

        // Modulus
        tlvWriter.writeTag(CONST_TAG_MODULUS);
        tlvWriter.writeLength(keyPair.getKeyLength());

        // The modulus data must be written manually because of how RSAPublicKey works
        offset = tlvWriter.getOffset();
        offset += keyPair.getModulus(scratch, offset);
        tlvWriter.setOffset(offset); // Move the current position forward

        // Exponent
        tlvWriter.writeTag(CONST_TAG_EXPONENT);
        tlvWriter.writeLength((short)3); // Hack! Why can't we get the size from RSAPublicKey?
        offset = tlvWriter.getOffset();
        offset += keyPair.getPublicExponent(scratch, offset);
        tlvWriter.setOffset(offset); // Move the current position forward

        length = tlvWriter.finish();
        chainBuffer.setOutgoing(scratch, (short)0, length, true);

        // Done, return the length of the object we are writing back
        return length;
    }
/**
     * The GENERATE ASYMMETRIC KEY PAIR card command initiates the generation and storing in the
     * card of the reference data of an asymmetric key pair, i.e., a public key and a private key.
     * The public key of the generated key pair is returned as the response to the command. If there
     * is reference data currently associated with the key reference, it is replaced in full by the
     * generated data.
     *
     * @param buffer The incoming APDU buffer
     * @param offset The offset of the CDATA element
     * @param length The length of the CDATA element
     * @return The length of the return data
     */
The GENERATE ASYMMETRIC KEY PAIR card command initiates the generation and storing in the
card of the reference data of an asymmetric key pair, i.e., a public key and a private key.
The public key of the generated key pair is returned as the response to the command. If there
is reference data currently associated with the key reference, it is replaced in full by the
generated data.

@param buffer The incoming APDU buffer
@param offset The offset of the CDATA element
@param length The length of the CDATA element
@return The length of the return data
The GENERATE ASYMMETRIC KEY PAIR card command initiates the generation and storing in the card of the reference data of an asymmetric key pair i . e . a public key and a private key . The public key of the generated key pair is returned as the response to the command . If there is reference data currently associated with the key reference it is replaced in full by the generated data . @param buffer The incoming APDU buffer @param offset The offset of the CDATA element @param length The length of the CDATA element @return The length of the return data
public short generateAsymmetricKeyPair(byte[] buffer, short offset, short length) {
        final byte CONST_TAG_TEMPLATE		= (byte)0xAC;
        final byte CONST_TAG_MECHANISM		= (byte)0x80;
        final byte CONST_TAG_PARAMETER 		= (byte)0x81;
        final short CONST_TAG_RESPONSE		= (short)0x7F49;
        final byte CONST_TAG_MODULUS		= (byte)0x81; 
        final byte CONST_TAG_EXPONENT		= (byte)0x82; 
         PRE-CONDITIONS
         PRE-CONDITION 1 - The access rules must be satisfied for administrative access
        if (!cspPIV.checkAccessModeAdmin(false)) {
            ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
        }
         PRE-CONDITION 2 - The 'TEMPLATE' tag must be present in the supplied buffer
        if (buffer[offset++] != CONST_TAG_TEMPLATE) {
            ISOException.throwIt(ISO7816.SW_WRONG_DATA);
        }
         Skip the length byte
        offset++;
         PRE-CONDITION 3 - The 'MECHANISM' tag must be present in the supplied buffer
        if (buffer[offset++] != CONST_TAG_MECHANISM) {
            ISOException.throwIt(ISO7816.SW_WRONG_DATA);
        }
         PRE-CONDITION 4 - The 'MECHANISM' tag must have a length of 1
        if (buffer[offset++] != (short)1) {
            ISOException.throwIt(ISO7816.SW_WRONG_DATA);
        }
		 PRE-CONDITION 5 - The 'MECHANISM' tag value must be one of the supported mechanisms
		if (buffer[offset] != PIV.ID_ALG_RSA_1024 && buffer[offset] != PIV.ID_ALG_RSA_2048) {
			ISOException.throwIt(ISO7816.SW_WRONG_DATA);
		}
         NOTE: We ignore the existence of the 'PARAMETER' tag, because according to SP800-78-4 the
         RSA public exponent is now fixed to 65537 (Section 3.1 PIV Cryptographic Keys).
         Since we don't support ECC algorithms yet, we have no other reason to read it.
         PRE-CONDITION 5 - The key reference and mechanism must point to an existing key
        PIVKeyObject key = cspPIV.selectKey(buffer[ISO7816.OFFSET_P2], buffer[offset]);
        if (key == null) {			
			 NOTE: The error message we return here is different dependant on whether the key is bad (6A86),
			 		 or the mechanism is bad (6A80) (See SP800-73-4 3.3.2 Generate Asymmetric Keypair). 
			if (!cspPIV.keyExists(buffer[ISO7816.OFFSET_P2])) {
				 The key reference is bad
				ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
			} else {
				 The mechanism is bad
				ISOException.throwIt(ISO7816.SW_WRONG_DATA);			
			}
        }
         PRE-CONDITION 6 - The key must be an assymetric key (key pair)
        if (!(key instanceof PIVKeyObjectPKI)) {
            ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
        }
         EXECUTION STEPS
         STEP 1 - Generate the key pair
        PIVKeyObjectPKI keyPair = (PIVKeyObjectPKI)key;
        keyPair.generate();
         STEP 2 - Prepare the outgoing public key
         NOTE: We only support RSA keys in the current implementation so we're just direct casting.
        		 Ideally we would use a factory to support multiple assymetric algorithms, but not today.
        tlvWriter.init(scratch, (short)0, key.getKeyLength(), CONST_TAG_RESPONSE);
         Modulus
        tlvWriter.writeTag(CONST_TAG_MODULUS);
        tlvWriter.writeLength(keyPair.getKeyLength());
         The modulus data must be written manually because of how RSAPublicKey works
        offset = tlvWriter.getOffset();
        offset += keyPair.getModulus(scratch, offset);
        tlvWriter.setOffset(offset);  Move the current position forward
         Exponent
        tlvWriter.writeTag(CONST_TAG_EXPONENT);
        tlvWriter.writeLength((short)3);  Hack! Why can't we get the size from RSAPublicKey?
        offset = tlvWriter.getOffset();
        offset += keyPair.getPublicExponent(scratch, offset);
        tlvWriter.setOffset(offset);  Move the current position forward
        length = tlvWriter.finish();
        chainBuffer.setOutgoing(scratch, (short)0, length, true);
         Done, return the length of the object we are writing back
        return length;
    }
public short generateAsymmetricKeyPair ( byte [ ] buffer , short offset , short length ) { final byte CONST_TAG_TEMPLATE = ( byte ) 0xAC ; final byte CONST_TAG_MECHANISM = ( byte ) 0x80 ; final byte CONST_TAG_PARAMETER = ( byte ) 0x81 ; final short CONST_TAG_RESPONSE = ( short ) 0x7F49 ; final byte CONST_TAG_MODULUS = ( byte ) 0x81 ; final byte CONST_TAG_EXPONENT = ( byte ) 0x82 ; if ( ! cspPIV . checkAccessModeAdmin ( false ) ) { ISOException . throwIt ( ISO7816 . SW_SECURITY_STATUS_NOT_SATISFIED ) ; } if ( buffer [ offset ++ ] != CONST_TAG_TEMPLATE ) { ISOException . throwIt ( ISO7816 . SW_WRONG_DATA ) ; } offset ++ ; if ( buffer [ offset ++ ] != CONST_TAG_MECHANISM ) { ISOException . throwIt ( ISO7816 . SW_WRONG_DATA ) ; } if ( buffer [ offset ++ ] != ( short ) 1 ) { ISOException . throwIt ( ISO7816 . SW_WRONG_DATA ) ; } PIVKeyObject key = cspPIV . selectKey ( buffer [ ISO7816 . OFFSET_P2 ] , buffer [ offset ] ) ; if ( key == null ) { if ( ! cspPIV . keyExists ( buffer [ ISO7816 . OFFSET_P2 ] ) ) { ISOException . throwIt ( ISO7816 . SW_INCORRECT_P1P2 ) ; } else { ISOException . throwIt ( ISO7816 . SW_WRONG_DATA ) ; } } if ( ! ( key instanceof PIVKeyObjectPKI ) ) { ISOException . throwIt ( ISO7816 . SW_INCORRECT_P1P2 ) ; } PIVKeyObjectPKI keyPair = ( PIVKeyObjectPKI ) key ; keyPair . generate ( ) ; tlvWriter . init ( scratch , ( short ) 0 , key . getKeyLength ( ) , CONST_TAG_RESPONSE ) ; tlvWriter . writeTag ( CONST_TAG_MODULUS ) ; tlvWriter . writeLength ( keyPair . getKeyLength ( ) ) ; offset = tlvWriter . getOffset ( ) ; offset += keyPair . getModulus ( scratch , offset ) ; tlvWriter . setOffset ( offset ) ; tlvWriter . writeTag ( CONST_TAG_EXPONENT ) ; tlvWriter . writeLength ( ( short ) 3 ) ; offset = tlvWriter . getOffset ( ) ; offset += keyPair . getPublicExponent ( scratch , offset ) ; tlvWriter . setOffset ( offset ) ; length = tlvWriter . finish ( ) ; chainBuffer . setOutgoing ( scratch , ( short ) 0 , length , true ) ; return length ; }
The GENERATE ASYMMETRIC KEY PAIR card command initiates the generation and storing in the
 card of the reference data of an asymmetric key pair, i.e., a public key and a private key.
The GENERATE ASYMMETRIC KEY PAIR card command initiates the generation and storing in the card of the reference data of an asymmetric key pair i . e . a public key and a private key .
// RSA - The modulus // RSA - The public exponent // // PRE-CONDITIONS // // PRE-CONDITION 1 - The access rules must be satisfied for administrative access // PRE-CONDITION 2 - The 'TEMPLATE' tag must be present in the supplied buffer // Skip the length byte // PRE-CONDITION 3 - The 'MECHANISM' tag must be present in the supplied buffer // PRE-CONDITION 4 - The 'MECHANISM' tag must have a length of 1 // PRE-CONDITION 5 - The 'MECHANISM' tag value must be one of the supported mechanisms //if (buffer[offset] != PIV.ID_ALG_RSA_1024 && buffer[offset] != PIV.ID_ALG_RSA_2048) { //ISOException.throwIt(ISO7816.SW_WRONG_DATA); //} // // NOTE: We ignore the existence of the 'PARAMETER' tag, because according to SP800-78-4 the // RSA public exponent is now fixed to 65537 (Section 3.1 PIV Cryptographic Keys). // Since we don't support ECC algorithms yet, we have no other reason to read it. // // PRE-CONDITION 5 - The key reference and mechanism must point to an existing key // NOTE: The error message we return here is different dependant on whether the key is bad (6A86), // 		 or the mechanism is bad (6A80) (See SP800-73-4 3.3.2 Generate Asymmetric Keypair).  // The key reference is bad // The mechanism is bad // PRE-CONDITION 6 - The key must be an assymetric key (key pair) // // EXECUTION STEPS // // STEP 1 - Generate the key pair // STEP 2 - Prepare the outgoing public key // // NOTE: We only support RSA keys in the current implementation so we're just direct casting. //		 Ideally we would use a factory to support multiple assymetric algorithms, but not today. // // Modulus // The modulus data must be written manually because of how RSAPublicKey works // Move the current position forward // Exponent // Hack! Why can't we get the size from RSAPublicKey? // Move the current position forward // Done, return the length of the object we are writing back