Java Code Examples for javacard.framework.ISOException#throwIt()

The following examples show how to use javacard.framework.ISOException#throwIt() . 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: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 7 votes vote down vote up
/**
 * Retrieves the Key object to be used w/ the specified key number, key type
 * (KEY_XX) and size. If exists, check it has the proper key type If not,
 * creates it.
 * 
 * @return Retrieved Key object or throws SW_UNATUTHORIZED,
 *         SW_OPERATION_NOT_ALLOWED
 */
private Key getKey(byte key_nb, byte key_type, short key_size) {
	
	if (eckeys[key_nb] == null) {
		// We have to create the Key
		eckeys[key_nb] = KeyBuilder.buildKey(key_type, key_size, false);
	} else {
		// Key already exists: check size & type
		/*
		 * TODO: As an option, we could just discard and recreate if not of
		 * the correct type, but creates trash objects
		 */
		if ((eckeys[key_nb].getSize() != key_size) || (eckeys[key_nb].getType() != key_type))
			ISOException.throwIt(SW_OPERATION_NOT_ALLOWED);
	}
	return eckeys[key_nb];
}
 
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: NdefApplet.java    From openjavacard-ndef with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Access a file for writing
 *
 * This function serves to perform precondition checks
 * before actually operating on a file in a write operation.
 *
 * If this function succeeds then the given fileId was
 * valid, security access has been granted and writing
 * of data for this file is possible.
 *
 * @param fileId of the file to be written
 * @return data array of the file
 * @throws ISOException on error
 */
private byte[] accessFileForWrite(short fileId) throws ISOException {
    byte[] file = null;
    byte access = FILE_ACCESS_NONE;
    // CC can not be written
    if(fileId == FILEID_NDEF_CAPABILITIES) {
        ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
    }
    // select relevant data
    if(fileId == FILEID_NDEF_DATA) {
        file = dataFile;
        access = dataWriteAccess;
    }
    // check that we got something
    if(file == null) {
        ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }
    // perform access checks
    if(!checkAccess(file, access)) {
        ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
    }
    return file;
}
 
Example 4
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 6 votes vote down vote up
/**
 * This function returns a 2 byte bit mask of the available PINs that are currently in
 * use. Each set bit corresponds to an active PIN.
 * 
 *  ins: 0x48
 *  p1: 0x00
 *  p2: 0x00
 *  data: none
 *  return: [RFU(1b) | PIN_mask(1b)]
 */
private short ListPINs(APDU apdu, byte[] buffer) {
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	
	// Checking P1 & P2
	if (buffer[ISO7816.OFFSET_P1] != (byte) 0x00)
		ISOException.throwIt(SW_INCORRECT_P1);
	if (buffer[ISO7816.OFFSET_P2] != (byte) 0x00)
		ISOException.throwIt(SW_INCORRECT_P2);
	byte expectedBytes = (byte) (buffer[ISO7816.OFFSET_LC]);
	if (expectedBytes != (short) 2)
		ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
	// Build the PIN bit mask
	short mask = (short) 0x00;
	short b;
	for (b = (short) 0; b < MAX_NUM_PINS; b++)
		if (pins[b] != null)
			mask |= (short) (((short) 0x01) << b);
	// Fill the buffer
	Util.setShort(buffer, (short) 0, mask);
	// Send response
	return (short)2;
}
 
Example 5
Source File: Bignat.java    From JCMathLib with MIT License 6 votes vote down vote up
/**
 * Copies content of {@code other} into this and set size of this to {@code other}. 
 * The size attribute (returned by length()) is updated. If {@code other}
 * is longer than maximum capacity of this, internal buffer is reallocated if enabled 
 * (ALLOW_RUNTIME_REALLOCATION), otherwise exception is thrown.
 * @param other 
 *            Bignat to clone into this object.
 */    
public void clone(Bignat other) { 
    // Reallocate array only if current array cannot store the other value and reallocation is enabled by ALLOW_RUNTIME_REALLOCATION
    if (this.max_size < other.length()) {
        // Reallocation necessary
        if (ALLOW_RUNTIME_REALLOCATION) {
            allocate_storage_array(other.length(), this.allocatorType);
        }
        else {
            ISOException.throwIt(ReturnCodes.SW_BIGNAT_REALLOCATIONNOTALLOWED);
        }
    }
    
    // copy value from other into proper place in this (this can be longer than other so rest of bytes wil be filled with 0)
    other.copy_to_buffer(this.value, (short) 0);
    if (this.max_size > other.length()) {
        Util.arrayFillNonAtomic(this.value, other.length(), (short) (this.max_size - other.length()), (byte) 0);
    }
    this.size = other.length();
}
 
Example 6
Source File: ObjectLocker.java    From JCMathLib with MIT License 6 votes vote down vote up
/**
 * Register new object for lock guarding. 
 * @param objToLock object to be guarded
 * @return index to internal array where registered object is stored (if known, lock/unlock is faster)
 */
public short registerLock(Object objToLock) {
    short i;
    for (i = 0; i < (short) lockedObjects.length; i += 2) {
        if (lockedObjects[i] == null) {
            // Free slot found
            lockedObjects[i] = objToLock;
            lockedObjects[(short) (i + 1)] = null; // null means array is unlocked
            lockedObjectsPersistent[i] = objToLock; // Store same into persistent array as well
            lockedObjectsPersistent[(short) (i + 1)] = null; 
            return i; // Return index for potential speedup of locking
        }
    }
    ISOException.throwIt(ReturnCodes.SW_LOCK_NOFREESLOT);
    return -1;
}
 
Example 7
Source File: TransitApplet.java    From JCMathLib with MIT License 5 votes vote down vote up
/**
 * Credits the account of the passed-in amount.
 * 
 * Request Message: [1-byte Credit Amount]
 * 
 * Response Message: []
 * 
 * @param buffer
 *            The APDU buffer
 * @param messageOffset
 *            The offset of the request message content in the APDU buffer
 * @param messageLength
 *            The length of the request message content.
 * @return The offset at which content can be appended to the response
 *         message
 */
private short credit(byte[] buffer, short messageOffset, short messageLength) {

    // Check access authorization
    if (!pin.isValidated()) {
        ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
    }

    // Request Message: [1-byte Credit Amount]

    if (messageLength != 1) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // Get credit amount from request message
    byte creditAmount = buffer[messageOffset];

    // Check credit amount
    if ((creditAmount > MAX_CREDIT_AMOUNT) || (creditAmount < 0)) {
        ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
    }

    // Check the new balance
    if ((short) (balance + creditAmount) > MAX_BALANCE) {
        ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);
    }

    // Credit the amount
    balance += creditAmount;

    // Response Message: []

    return 0;
}
 
Example 8
Source File: NdefApplet.java    From openjavacard-ndef with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Create and initialize the CAPABILITIES file
 *
 * @param dataSize to be allocated
 * @return an array for use as the CC file
 */
private byte[] makeCaps(short dataSize) {
    short capsLen = (short)(CC_LEN_HEADER + 2 + CC_LEN_NDEF_FILE_CONTROL);
    byte[] caps = new byte[capsLen];

    short pos = 0;

    // CC length
    pos = Util.setShort(caps, pos,  capsLen);
    // mapping version
    caps[pos++] = NDEF_MAPPING_VERSION;
    // maximum read size
    pos = Util.setShort(caps, pos, NDEF_MAX_READ);
    // maximum write size
    pos = Util.setShort(caps, pos, NDEF_MAX_WRITE);

    // NDEF File Control TLV
    caps[pos++] = CC_TAG_NDEF_FILE_CONTROL;
    caps[pos++] = CC_LEN_NDEF_FILE_CONTROL;
    // file ID
    pos = Util.setShort(caps, pos, FILEID_NDEF_DATA);
    // file size
    pos = Util.setShort(caps, pos, dataSize);
    // read access
    caps[pos++] = NDEF_READ_ACCESS;
    // write access
    caps[pos++] = NDEF_WRITE_ACCESS;

    // check consistency
    if(pos != capsLen) {
        ISOException.throwIt(ISO7816.SW_UNKNOWN);
    }

    // return the file
    return caps;
}
 
Example 9
Source File: TransmitManager.java    From GidsApplet with GNU General Public License v3.0 5 votes vote down vote up
public short doChainingOrExtAPDUFlash(APDU apdu) throws ISOException {
    // allocate flash buffer only when needed - it can remain for the rest of the card life
    if (flash_buf == null)
    {
        try {
            flash_buf = new byte[FLASH_BUF_SIZE];
        } catch(SystemException e) {
            if(e.getReason() == SystemException.NO_RESOURCE) {
                ISOException.throwIt(ISO7816.SW_FILE_FULL);
            }
            ISOException.throwIt(ISO7816.SW_UNKNOWN);
        }
    }
    return doChainingOrExtAPDUWithBuffer(apdu, flash_buf, FLASH_BUF_SIZE);
}
 
Example 10
Source File: TransmitManager.java    From GidsApplet with GNU General Public License v3.0 5 votes vote down vote up
private short doChainingOrExtAPDUWithBuffer(APDU apdu, byte[] databuffer, short bufferlen) throws ISOException {
    
    short recvLen = apdu.setIncomingAndReceive();
    byte[] buf = apdu.getBuffer();
    // Receive data (short or extended).
    while (recvLen > 0) {
        if((short)(chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] + recvLen) > bufferlen) {
            ISOException.throwIt(ISO7816.SW_FILE_FULL);
        }
        Util.arrayCopyNonAtomic(buf, ISO7816.OFFSET_CDATA, databuffer, chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS], recvLen);
        chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] += recvLen;
        recvLen = apdu.receiveBytes(ISO7816.OFFSET_CDATA);
    }

    if(isCommandChainingCLA(apdu)) {
        // We are still in the middle of a chain, otherwise there would not have been a chaining CLA.
        // Make sure the caller does not forget to return as the data should only be interpreted
        // when the chain is completed (when using this method).
        ISOException.throwIt(ISO7816.SW_NO_ERROR);
        return (short)0;
    } else {
        // Chain has ended or no chaining.
        // We did receive the data, everything is fine.
        // Reset the current position in ram_buf.
        recvLen = (short) (recvLen + chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS]);
        chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] = 0;
        return recvLen;
    }
}
 
Example 11
Source File: NdefApplet.java    From openjavacard-ndef with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Process an UPDATE BINARY command
 *
 * Supports simple writes at any offset.
 *
 * The amount of data that can be written in one
 * operation is limited both by maximum C-APDU
 * length and the maximum write size NDEF_MAX_WRITE.
 *
 * @param apdu to process
 * @throws ISOException on error
 */
private void processUpdateBinary(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();

    // access the file
    byte[] file = accessFileForWrite(vars[VAR_SELECTED_FILE]);

    // get and check the write offset
    short offset = Util.getShort(buffer, ISO7816.OFFSET_P1);
    if(offset < 0 || offset >= file.length) {
        ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
    }

    // receive data
    short lc = apdu.setIncomingAndReceive();

    // check the input size
    if(lc > NDEF_MAX_WRITE) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // file limit checks
    short limit = (short)(offset + lc);
    if(limit < 0 || limit >= file.length) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // perform the update
    Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, file, offset, lc);
}
 
Example 12
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 5 votes vote down vote up
/**
 * This function unblocks a PIN number using the unblock code specified in the
 * DATA portion. The P3 byte specifies the unblock code length. 
 * 
 * ins: 0x46
 * p1: PIN number (0x00-0x07)
 * p2: 0x00
 * data: [PUK] 
 * return: none (throws an exception in case of wrong PUK)
 */
private short UnblockPIN(APDU apdu, byte[] buffer) {
	byte pin_nb = buffer[ISO7816.OFFSET_P1];
	if ((pin_nb < 0) || (pin_nb >= MAX_NUM_PINS))
		ISOException.throwIt(SW_INCORRECT_P1);
	OwnerPIN pin = pins[pin_nb];
	OwnerPIN ublk_pin = ublk_pins[pin_nb];
	if (pin == null)
		ISOException.throwIt(SW_INCORRECT_P1);
	if (ublk_pin == null)
		ISOException.throwIt(SW_INTERNAL_ERROR);
	// If the PIN is not blocked, the call is inconsistent
	if (pin.getTriesRemaining() != 0)
		ISOException.throwIt(SW_OPERATION_NOT_ALLOWED);
	if (buffer[ISO7816.OFFSET_P2] != 0x00)
		ISOException.throwIt(SW_INCORRECT_P2);
	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
	/*
	 * Here I suppose the PIN code is small enough to fit into the buffer
	 * TODO: Verify the assumption and eventually adjust code to support
	 * reading PIN in multiple read()s
	 */
	if (!CheckPINPolicy(buffer, ISO7816.OFFSET_CDATA, (byte) bytesLeft))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	byte triesRemaining	= ublk_pin.getTriesRemaining();
	if (triesRemaining == (byte) 0x00)
		ISOException.throwIt(SW_IDENTITY_BLOCKED);
	if (!ublk_pin.check(buffer, ISO7816.OFFSET_CDATA, (byte) bytesLeft))
		ISOException.throwIt((short)(SW_PIN_FAILED + triesRemaining - 1));
	
	pin.resetAndUnblock();
	
	return (short)0;
}
 
Example 13
Source File: EC_Consts.java    From ECTester with MIT License 5 votes vote down vote up
public static short toX962(byte form, byte[] outputBuffer, short outputOffset, byte[] xBuffer, short xOffset, short xLength, byte[] yBuffer, short yOffset, short yLength) {
    short size = 1;
    size += xLength;

    short offset = outputOffset;
    outputBuffer[offset] = 0;
    switch (form) {
        case X962_UNCOMPRESSED:
            outputBuffer[offset] = 4;
            break;
        case X962_HYBRID:
            outputBuffer[offset] = 4;
        case X962_COMPRESSED: /* fallthrough */
            byte yLSB = yBuffer[(short) (yOffset + yLength)];
            byte yBit = (byte) (yLSB & 0x01);

            if (yBit == 1) {
                outputBuffer[offset] += 3;
            } else {
                outputBuffer[offset] += 2;
            }
            break;
        default:
            ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
    }
    offset += 1;

    offset = Util.arrayCopyNonAtomic(xBuffer, xOffset, outputBuffer, offset, xLength);
    if (form == X962_HYBRID || form == X962_UNCOMPRESSED) {
        Util.arrayCopyNonAtomic(yBuffer, yOffset, outputBuffer, offset, yLength);
        size += yLength;
    }

    return size;
}
 
Example 14
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 5 votes vote down vote up
/** 
 * This function creates a PIN with parameters specified by the P1, P2 and DATA
 * values. P2 specifies the maximum number of consecutive unsuccessful
 * verifications before the PIN blocks. PIN can be created only if one of the logged identities
 * allows it. 
 * 
 * ins: 0x40
 * p1: PIN number (0x00-0x07)
 * p2: max attempt number
 * data: [PIN_size(1b) | PIN | UBLK_size(1b) | UBLK] 
 * return: none
 */
private short CreatePIN(APDU apdu, byte[] buffer) {
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	
	byte pin_nb = buffer[ISO7816.OFFSET_P1];
	byte num_tries = buffer[ISO7816.OFFSET_P2];
	
	if ((pin_nb < 0) || (pin_nb >= MAX_NUM_PINS) || (pins[pin_nb] != null))
		ISOException.throwIt(SW_INCORRECT_P1);
	/* Allow pin lengths > 127 (useful at all ?) */
	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
	// At least 1 character for PIN and 1 for unblock code (+ lengths)
	if (bytesLeft < 4)
		ISOException.throwIt(SW_INVALID_PARAMETER);
	byte pin_size = buffer[ISO7816.OFFSET_CDATA];
	if (bytesLeft < (short) (1 + pin_size + 1))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	if (!CheckPINPolicy(buffer, (short) (ISO7816.OFFSET_CDATA + 1), pin_size))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	byte ucode_size = buffer[(short) (ISO7816.OFFSET_CDATA + 1 + pin_size)];
	if (bytesLeft != (short) (1 + pin_size + 1 + ucode_size))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	if (!CheckPINPolicy(buffer, (short) (ISO7816.OFFSET_CDATA + 1 + pin_size + 1), ucode_size))
		ISOException.throwIt(SW_INVALID_PARAMETER);
	pins[pin_nb] = new OwnerPIN(num_tries, PIN_MAX_SIZE);
	pins[pin_nb].update(buffer, (short) (ISO7816.OFFSET_CDATA + 1), pin_size);
	ublk_pins[pin_nb] = new OwnerPIN((byte) 3, PIN_MAX_SIZE);
	// Recycle variable pin_size
	pin_size = (byte) (ISO7816.OFFSET_CDATA + 1 + pin_size + 1);
	ublk_pins[pin_nb].update(buffer, pin_size, ucode_size);
	
	return (short)0;
}
 
Example 15
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/** 
 * This function returns the public key associated with a particular private key stored 
 * in the applet. The exact key blob contents depend on the key�s algorithm and type. 
 * 
 * ins: 0x35
 * p1: private key number (0x00-0x0F)
 * p2: 0x00
 * data: none 
 * return(SECP256K1): [coordx_size(2b) | pubkey_coordx | sig_size(2b) | sig]
 */
private short getPublicKeyFromPrivate(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);
	
	byte key_nb = buffer[ISO7816.OFFSET_P1];
	if ((key_nb < 0) || (key_nb >= MAX_NUM_KEYS))
		ISOException.throwIt(SW_INCORRECT_P1);
	
	Key key = eckeys[key_nb];
	// check type and size
	if ((key == null) || !key.isInitialized())
		ISOException.throwIt(SW_INCORRECT_P1);
	if (key.getType() != KeyBuilder.TYPE_EC_FP_PRIVATE)
		ISOException.throwIt(SW_INCORRECT_ALG);		
	if (key.getSize()!= LENGTH_EC_FP_256)
		ISOException.throwIt(SW_INCORRECT_ALG);
	// check the curve param
	if(!Secp256k1.checkCurveParameters((ECPrivateKey)key, recvBuffer, (short)0))
		ISOException.throwIt(SW_INCORRECT_ALG);
			
	// compute the corresponding partial public key...
       keyAgreement.init((ECPrivateKey)key);
       short coordx_size=(short)32;
   	keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, buffer, (short)1); //pubkey in uncompressed form
    Util.setShort(buffer, (short)0, coordx_size);
       
       // sign fixed message
       sigECDSA.init(key, Signature.MODE_SIGN);
       short sign_size= sigECDSA.sign(buffer, (short)0, (short)(coordx_size+2), buffer, (short)(coordx_size+4));
       Util.setShort(buffer, (short)(coordx_size+2), 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... 
       return (short)(2+coordx_size+2+sign_size);
}
 
Example 16
Source File: TransmitManager.java    From GidsApplet with GNU General Public License v3.0 4 votes vote down vote up
public void processChainInitialization(APDU apdu) {
    byte buffer[] = apdu.getBuffer();
    byte ins = buffer[ISO7816.OFFSET_INS];
    // Command chaining checks & initialization
    if(chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_INS] != 0 || isCommandChainingCLA(apdu)) {
        short p1p2 = Util.getShort(buffer, ISO7816.OFFSET_P1);
        /*
         * Command chaining only for:
         * 	- PERFORM SECURITY OPERATION
         * 	- GENERATE ASYMMETRIC KEYKAIR
         * 	- PUT DATA
         * when not using extended APDUs.
         */
        if( (ins != GidsApplet.INS_PERFORM_SECURITY_OPERATION
                && ins != GidsApplet.INS_GENERATE_ASYMMETRIC_KEYPAIR
                && ins != GidsApplet.INS_PUT_DATA)) {
            ISOException.throwIt(ErrorCode.SW_COMMAND_CHAINING_NOT_SUPPORTED);
        }

        if(chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_INS] == 0
                && chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_P1P2] == 0) {
            /* A new chain is starting - set the current INS and P1P2. */
            if(ins == 0) {
                ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
            }
            chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_INS] = ins;
            chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_P1P2] = p1p2;
        } else if(chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_INS] != ins
                  || chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_P1P2] != p1p2) {
            /* The current chain is not yet completed,
             * but an apdu not part of the chain had been received. */
            ISOException.throwIt(ErrorCode.SW_COMMAND_NOT_ALLOWED_GENERAL);
        } else if(!isCommandChainingCLA(apdu)) {
            /* A chain is ending, set the current INS and P1P2 to zero to indicate that. */
            chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_INS] = 0;
            chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_P1P2] = 0;
        }
    }

    // If the card expects a GET RESPONSE, no other operation should be requested.
    if(chaining_cache[RAM_CHAINING_CACHE_OFFSET_BYTES_REMAINING] > 0 && ins != GidsApplet.INS_GET_RESPONSE) {
        // clear the buffer
        Clear(true);
    }
    if (ins != GidsApplet.INS_PUT_DATA) {
        clearCachedRecord();
    }
}
 
Example 17
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * This function allows to decrypt a secure channel message
 *  
 *  ins: 0x82
 *  
 *  p1: 0x00 (RFU)
 *  p2: 0x00 (RFU)
 *  data: [IV(16b) | data_size(2b) | encrypted_command | mac_size(2b) | mac]
    *  
    *  return: [decrypted command]
    *   
 */
private short ProcessSecureChannel(APDU apdu, byte[] buffer){
	
       short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
       short offset = ISO7816.OFFSET_CDATA;
       
       if (!initialized_secure_channel){
       	ISOException.throwIt(SW_SECURE_CHANNEL_UNINITIALIZED);
       }
       
       // check hmac
       if (bytesLeft<18)
       	ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       short sizein = Util.getShort(buffer, (short) (offset+SIZE_SC_IV));
       if (bytesLeft<(short)(SIZE_SC_IV+2+sizein+2))
       	ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       short sizemac= Util.getShort(buffer, (short) (offset+SIZE_SC_IV+2+sizein));
       if (sizemac != (short)20)
       	ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_MAC);
       if (bytesLeft<(short)(SIZE_SC_IV+2+sizein+2+sizemac))
       	ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       HmacSha160.computeHmacSha160(sc_buffer, OFFSET_SC_MACKEY, SIZE_SC_MACKEY, buffer, offset, (short)(SIZE_SC_IV+2+sizein), recvBuffer, (short)0);
       if ( Util.arrayCompare(recvBuffer, (short)0, buffer, (short)(offset+SIZE_SC_IV+2+sizein+2), (short)20) != (byte)0 )
       	ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_MAC);
       
       // process IV
       // IV received from client should be odd and strictly greater than locally saved IV
       // IV should be random (the 12 first bytes), never reused (the last 4 bytes counter) and different for send and receive
       if ((buffer[(short)(offset+SIZE_SC_IV-(short)1)] & (byte)0x01)==0x00)// should be odd
       	ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_IV);
       if ( !Biginteger.lessThan(sc_buffer, OFFSET_SC_IV_COUNTER, buffer, (short)(offset+SIZE_SC_IV_RANDOM), SIZE_SC_IV_COUNTER ) ) //and greater than local IV
       	ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_IV);
       // update local IV
       Util.arrayCopy(buffer, (short)(offset+SIZE_SC_IV_RANDOM), sc_buffer, OFFSET_SC_IV_COUNTER, SIZE_SC_IV_COUNTER);
       Biginteger.add1_carry(sc_buffer, OFFSET_SC_IV_COUNTER, SIZE_SC_IV_COUNTER);
    	randomData.generateData(sc_buffer, OFFSET_SC_IV_RANDOM, SIZE_SC_IV_RANDOM);
    	sc_aes128_cbc.init(sc_sessionkey, Cipher.MODE_DECRYPT, buffer, offset, SIZE_SC_IV);
       offset+=SIZE_SC_IV;
       bytesLeft-=SIZE_SC_IV;
       
       //decrypt command
       offset+=2;
       bytesLeft-=2;
       if (bytesLeft<sizein)
       	ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       short sizeout=sc_aes128_cbc.doFinal(buffer, offset, sizein, buffer, (short) (0));
       return sizeout;
}
 
Example 18
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 19
Source File: GidsPIN.java    From GidsApplet with GNU General Public License v3.0 4 votes vote down vote up
public void CheckLength(byte len) {
    if (len < minPINSize || len > maxPINSize) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
}
 
Example 20
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 3 votes vote down vote up
/**
 * DEPRECATED - Not necessary anymore when recovering the pubkey with ALG_EC_SVDP_DH_PLAIN_XY
 * A minimalist API is maintained for backward compatibility.
 * 
 * This function allows to compute the authentikey pubkey externally and 
 * store it in the secure memory cache for future use. 
 * This allows to speed up computation during derivation of non-hardened child.
 * 
 * ins: 0x75
 * p1: 
 * p2:
 * data: [coordx_size(2b) | coordx | sig_size(2b) | sig][coordy_size(2b) | coordy]
    *
 * returns: none
 */
private short setBIP32AuthentikeyPubkey(APDU apdu, byte[] buffer){
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	
       short pos=0;
	Util.setShort(buffer, pos, bip32_om.nb_elem_free); // number of slot available 
	pos += (short) 2;
	Util.setShort(buffer, pos, bip32_om.nb_elem_used); // number of slot used 
	pos += (short) 2;
	return pos;
}