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

        final byte CONST_TAG 		= (byte)0x5C;
        final byte CONST_TAG_MIN 	= (byte)0x01;
        final byte CONST_TAG_MAX 	= (byte)0x03;
        final byte CONST_DATA		= (byte)0x53;

        final byte CONST_TAG_DISCOVERY		= (byte)0x7E;
        final byte CONST_TAG_BIOMETRIC_1	= (byte)0x7F;
        final byte CONST_TAG_BIOMETRIC_2	= (byte)0x61;
        final byte CONST_TAG_NORMAL_1		= (byte)0x5F;
        final byte CONST_TAG_NORMAL_2		= (byte)0xC1;

        final short CONST_LEN_DISCOVERY	= (short)0x01;
        final short CONST_LEN_BIOMETRIC	= (short)0x02;

        //
        // PRE-CONDITIONS
        //

        // Store the supplied data offset so we can use it to calculate the length of the object later
        short initialOffset = offset;

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

        byte id = 0;

        // SPECIAL OBJECT - DISCOVERY OBJECT
        // PRE-CONDITION 2A - If the special 'DISCOVERY OBJECT' is being written, the tag specified by
        //					  CONST_TAG_DISCOVERY must be present
        if (buffer[offset] == CONST_TAG_DISCOVERY) {
            id = CONST_TAG_DISCOVERY;
            // We don't move the buffer for this special object to include the special data object tag
        }

        // SPECIAL OBJECT - BIOMETRIC GROUP TEMPLATE
        // PRE-CONDITION 2B - If the special 'BIOMETRIC GROUP TEMPLATE' is being written, the tag values
        //					  specified by CONST_TAG_BIOMETRIC_1 and CONST_TAG_BIOMETRIC_2 must be present
        else if (buffer[offset] == CONST_TAG_BIOMETRIC_1) {
            if ((short)(buffer[offset] + 1) != CONST_TAG_BIOMETRIC_2) ISOException.throwIt(SW_REFERENCE_NOT_FOUND);
            id = CONST_TAG_BIOMETRIC_2;
            // We don't move the buffer for this special object to include the special data object tag
        }

        //
        // ALL OTHER OBJECTS (Must have the TAG LIST value)
        //
        else if (buffer[offset] == CONST_TAG) {

            //
            // Retrieve the data object TAG identifier
            // NOTE: All objects in the datastore have had their tag reduced to one byte, which is
            //		 always the least significant byte of the tag.
            //

            offset++; // Move to the length field

            // PRE-CONDITION 3 - The 'TAG LIST' tag must have a length of between CONST_TAG_MIN and CONST_TAG_MAX
            if (buffer[offset] < CONST_TAG_MIN || buffer[offset] > CONST_TAG_MAX) {
                ISOException.throwIt(ISO7816.SW_WRONG_DATA);
            }

            offset++; // Move to the 1st byte of the tag
            if (buffer[offset] != CONST_TAG_NORMAL_1) ISOException.throwIt(SW_REFERENCE_NOT_FOUND);
            offset++; // Move to the 2nd byte
            if (buffer[offset] != CONST_TAG_NORMAL_2) ISOException.throwIt(SW_REFERENCE_NOT_FOUND);
            offset++; // Move to the 3rd byte
            id = buffer[offset]; // Store it as our object ID
            offset++; // Move to the DATA element

            // PRE-CONDITION 4 - The 'DATA' tag must be present in the supplied buffer
            if (buffer[offset] != CONST_DATA) {
                ISOException.throwIt(ISO7816.SW_WRONG_DATA);
            }
            // The offset now holds the correct position for writing the object, including the DATA tag
        }
        // Invalid Object
        else {
            ISOException.throwIt(SW_REFERENCE_NOT_FOUND);
        }


        // PRE-CONDITION 5 - The tag supplied in the 'TAG LIST' element must exist in the data store
        PIVDataObject obj = findDataObject(id);
        if (obj == null) {
            ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
        }

        //
        // EXECUTION STEPS
        //

        // STEP 1 - Calculate the total length of the object to allocate
        short objectLength = TLVReader.getLength(buffer, offset);
        objectLength += (short)(TLVReader.getDataOffset(buffer, offset) - offset);

        // STEP 2 - Allocate the data object
        obj.allocate(objectLength);

        // STEP 3 - Recalculate the length of the first write, to account for the tag element being removed
        length -= (short)(offset - initialOffset);

        // STEP 4 - Set up the incoming chainbuffer
        chainBuffer.setIncomingObject(obj.content, (short)0, objectLength, false);

        // STEP 5 - Start processing the first segment of data here so we can give it our modified offset/length
        chainBuffer.processIncomingObject(buffer, offset, length);
    }
/**
     * The PUT DATA card command completely replaces the data content of a single data object in
     * the PIV Card Application with new content.
     *
     * @param buffer The incoming APDU buffer
     * @param offset The starting offset of the CDATA section
     * @param length The length of the CDATA section
     */
The PUT DATA card command completely replaces the data content of a single data object in
the PIV Card Application with new content.

@param buffer The incoming APDU buffer
@param offset The starting offset of the CDATA section
@param length The length of the CDATA section
The PUT DATA card command completely replaces the data content of a single data object in the PIV Card Application with new content . @param buffer The incoming APDU buffer @param offset The starting offset of the CDATA section @param length The length of the CDATA section
public void putData(byte[] buffer, short offset, short length) {
        final byte CONST_TAG 		= (byte)0x5C;
        final byte CONST_TAG_MIN 	= (byte)0x01;
        final byte CONST_TAG_MAX 	= (byte)0x03;
        final byte CONST_DATA		= (byte)0x53;
        final byte CONST_TAG_DISCOVERY		= (byte)0x7E;
        final byte CONST_TAG_BIOMETRIC_1	= (byte)0x7F;
        final byte CONST_TAG_BIOMETRIC_2	= (byte)0x61;
        final byte CONST_TAG_NORMAL_1		= (byte)0x5F;
        final byte CONST_TAG_NORMAL_2		= (byte)0xC1;
        final short CONST_LEN_DISCOVERY	= (short)0x01;
        final short CONST_LEN_BIOMETRIC	= (short)0x02;
         PRE-CONDITIONS
         Store the supplied data offset so we can use it to calculate the length of the object later
        short initialOffset = offset;
         PRE-CONDITION 1 - The access rules must be satisfied for administrative access
        if (!cspPIV.checkAccessModeAdmin(false) ) {
            ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
        }
        byte id = 0;
         SPECIAL OBJECT - DISCOVERY OBJECT
         PRE-CONDITION 2A - If the special 'DISCOVERY OBJECT' is being written, the tag specified by
        					  CONST_TAG_DISCOVERY must be present
        if (buffer[offset] == CONST_TAG_DISCOVERY) {
            id = CONST_TAG_DISCOVERY;
             We don't move the buffer for this special object to include the special data object tag
        }
         SPECIAL OBJECT - BIOMETRIC GROUP TEMPLATE
         PRE-CONDITION 2B - If the special 'BIOMETRIC GROUP TEMPLATE' is being written, the tag values
        					  specified by CONST_TAG_BIOMETRIC_1 and CONST_TAG_BIOMETRIC_2 must be present
        else if (buffer[offset] == CONST_TAG_BIOMETRIC_1) {
            if ((short)(buffer[offset] + 1) != CONST_TAG_BIOMETRIC_2) ISOException.throwIt(SW_REFERENCE_NOT_FOUND);
            id = CONST_TAG_BIOMETRIC_2;
             We don't move the buffer for this special object to include the special data object tag
        }
         ALL OTHER OBJECTS (Must have the TAG LIST value)
        else if (buffer[offset] == CONST_TAG) {
             Retrieve the data object TAG identifier
             NOTE: All objects in the datastore have had their tag reduced to one byte, which is
            		 always the least significant byte of the tag.
            offset++;  Move to the length field
             PRE-CONDITION 3 - The 'TAG LIST' tag must have a length of between CONST_TAG_MIN and CONST_TAG_MAX
            if (buffer[offset] < CONST_TAG_MIN || buffer[offset] > CONST_TAG_MAX) {
                ISOException.throwIt(ISO7816.SW_WRONG_DATA);
            }
            offset++;  Move to the 1st byte of the tag
            if (buffer[offset] != CONST_TAG_NORMAL_1) ISOException.throwIt(SW_REFERENCE_NOT_FOUND);
            offset++;  Move to the 2nd byte
            if (buffer[offset] != CONST_TAG_NORMAL_2) ISOException.throwIt(SW_REFERENCE_NOT_FOUND);
            offset++;  Move to the 3rd byte
            id = buffer[offset];  Store it as our object ID
            offset++;  Move to the DATA element
             PRE-CONDITION 4 - The 'DATA' tag must be present in the supplied buffer
            if (buffer[offset] != CONST_DATA) {
                ISOException.throwIt(ISO7816.SW_WRONG_DATA);
            }
             The offset now holds the correct position for writing the object, including the DATA tag
        }
         Invalid Object
        else {
            ISOException.throwIt(SW_REFERENCE_NOT_FOUND);
        }
         PRE-CONDITION 5 - The tag supplied in the 'TAG LIST' element must exist in the data store
        PIVDataObject obj = findDataObject(id);
        if (obj == null) {
            ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
        }
         EXECUTION STEPS
         STEP 1 - Calculate the total length of the object to allocate
        short objectLength = TLVReader.getLength(buffer, offset);
        objectLength += (short)(TLVReader.getDataOffset(buffer, offset) - offset);
         STEP 2 - Allocate the data object
        obj.allocate(objectLength);
         STEP 3 - Recalculate the length of the first write, to account for the tag element being removed
        length -= (short)(offset - initialOffset);
         STEP 4 - Set up the incoming chainbuffer
        chainBuffer.setIncomingObject(obj.content, (short)0, objectLength, false);
         STEP 5 - Start processing the first segment of data here so we can give it our modified offset/length
        chainBuffer.processIncomingObject(buffer, offset, length);
    }
public void putData ( byte [ ] buffer , short offset , short length ) { final byte CONST_TAG = ( byte ) 0x5C ; final byte CONST_TAG_MIN = ( byte ) 0x01 ; final byte CONST_TAG_MAX = ( byte ) 0x03 ; final byte CONST_DATA = ( byte ) 0x53 ; final byte CONST_TAG_DISCOVERY = ( byte ) 0x7E ; final byte CONST_TAG_BIOMETRIC_1 = ( byte ) 0x7F ; final byte CONST_TAG_BIOMETRIC_2 = ( byte ) 0x61 ; final byte CONST_TAG_NORMAL_1 = ( byte ) 0x5F ; final byte CONST_TAG_NORMAL_2 = ( byte ) 0xC1 ; final short CONST_LEN_DISCOVERY = ( short ) 0x01 ; final short CONST_LEN_BIOMETRIC = ( short ) 0x02 ; short initialOffset = offset ; if ( ! cspPIV . checkAccessModeAdmin ( false ) ) { ISOException . throwIt ( ISO7816 . SW_SECURITY_STATUS_NOT_SATISFIED ) ; } byte id = 0 ; if ( buffer [ offset ] == CONST_TAG_DISCOVERY ) { id = CONST_TAG_DISCOVERY ; } else if ( buffer [ offset ] == CONST_TAG_BIOMETRIC_1 ) { if ( ( short ) ( buffer [ offset ] + 1 ) != CONST_TAG_BIOMETRIC_2 ) ISOException . throwIt ( SW_REFERENCE_NOT_FOUND ) ; id = CONST_TAG_BIOMETRIC_2 ; } else if ( buffer [ offset ] == CONST_TAG ) { offset ++ ; if ( buffer [ offset ] < CONST_TAG_MIN || buffer [ offset ] > CONST_TAG_MAX ) { ISOException . throwIt ( ISO7816 . SW_WRONG_DATA ) ; } offset ++ ; if ( buffer [ offset ] != CONST_TAG_NORMAL_1 ) ISOException . throwIt ( SW_REFERENCE_NOT_FOUND ) ; offset ++ ; if ( buffer [ offset ] != CONST_TAG_NORMAL_2 ) ISOException . throwIt ( SW_REFERENCE_NOT_FOUND ) ; offset ++ ; id = buffer [ offset ] ; offset ++ ; if ( buffer [ offset ] != CONST_DATA ) { ISOException . throwIt ( ISO7816 . SW_WRONG_DATA ) ; } } else { ISOException . throwIt ( SW_REFERENCE_NOT_FOUND ) ; } PIVDataObject obj = findDataObject ( id ) ; if ( obj == null ) { ISOException . throwIt ( ISO7816 . SW_FILE_NOT_FOUND ) ; } short objectLength = TLVReader . getLength ( buffer , offset ) ; objectLength += ( short ) ( TLVReader . getDataOffset ( buffer , offset ) - offset ) ; obj . allocate ( objectLength ) ; length -= ( short ) ( offset - initialOffset ) ; chainBuffer . setIncomingObject ( obj . content , ( short ) 0 , objectLength , false ) ; chainBuffer . processIncomingObject ( buffer , offset , length ) ; }
The PUT DATA card command completely replaces the data content of a single data object in
 the PIV Card Application with new content.
The PUT DATA card command completely replaces the data content of a single data object in the PIV Card Application with new content .
// // PRE-CONDITIONS // // Store the supplied data offset so we can use it to calculate the length of the object later // PRE-CONDITION 1 - The access rules must be satisfied for administrative access // SPECIAL OBJECT - DISCOVERY OBJECT // PRE-CONDITION 2A - If the special 'DISCOVERY OBJECT' is being written, the tag specified by //					  CONST_TAG_DISCOVERY must be present // We don't move the buffer for this special object to include the special data object tag // SPECIAL OBJECT - BIOMETRIC GROUP TEMPLATE // PRE-CONDITION 2B - If the special 'BIOMETRIC GROUP TEMPLATE' is being written, the tag values //					  specified by CONST_TAG_BIOMETRIC_1 and CONST_TAG_BIOMETRIC_2 must be present // We don't move the buffer for this special object to include the special data object tag // // ALL OTHER OBJECTS (Must have the TAG LIST value) // // // Retrieve the data object TAG identifier // NOTE: All objects in the datastore have had their tag reduced to one byte, which is //		 always the least significant byte of the tag. // // Move to the length field // PRE-CONDITION 3 - The 'TAG LIST' tag must have a length of between CONST_TAG_MIN and CONST_TAG_MAX // Move to the 1st byte of the tag // Move to the 2nd byte // Move to the 3rd byte // Store it as our object ID // Move to the DATA element // PRE-CONDITION 4 - The 'DATA' tag must be present in the supplied buffer // The offset now holds the correct position for writing the object, including the DATA tag // Invalid Object // PRE-CONDITION 5 - The tag supplied in the 'TAG LIST' element must exist in the data store // // EXECUTION STEPS // // STEP 1 - Calculate the total length of the object to allocate // STEP 2 - Allocate the data object // STEP 3 - Recalculate the length of the first write, to account for the tag element being removed // STEP 4 - Set up the incoming chainbuffer // STEP 5 - Start processing the first segment of data here so we can give it our modified offset/length