javacard.framework.OwnerPIN Maven / Gradle / Ivy
Show all versions of jcardsim Show documentation
/*
* Copyright 2011 Licel LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javacard.framework;
/**
* This class represents an Owner PIN, implements Personal Identification Number
* functionality as defined in the PIN
interface, and
* provides the ability to update the PIN and thus owner functionality.
*
* The implementation of this class must protect against attacks based on program
* flow prediction. In addition, even if a transaction is in progress, update of
* internal state, such as the try counter, the validated flag, and the blocking state,
* shall not participate in the transaction during PIN presentation.
*
* If an implementation of this class creates transient arrays, it must ensure that they are
* CLEAR_ON_RESET
transient objects.
*
* The protected methods getValidatedFlag
and
* setValidatedFlag
allow a subclass
* of this class to optimize the storage for the validated boolean state.
*
* Some methods of instances of this class are only suitable for sharing when there exists
* a trust relationship among the applets. A typical shared usage would use
* a proxy PIN interface which extends both the PIN
interface and
* the Shareable
interface and re-declares the methods of the PIN interface.
*
* Any of the methods of the OwnerPIN
may be called with a transaction in
* progress. None of the methods of OwnerPIN
class initiate or alter the state
* of the transaction if one is in progress.
*
*/
public class OwnerPIN implements PIN {
private static final byte VALIDATED = 0;
private static final byte NUMFLAGS = 1;
private byte tryLimit;
private byte maxPINSize;
private byte pinValue[];
private byte pinSize;
// CHECK !!! Use transient array with size 1 element for store validation state
private boolean flags[];
// CHECK !!! Use transient array with size 1 element for store tries counter
private byte triesLeft[];
/**
* Constructor. Allocates a new PIN
instance with validated flag
* set to false
* @param tryLimit the maximum number of times an incorrect PIN can be presented. tryLimit
must be >=1
* @param maxPINSize the maximum allowed PIN size. maxPINSize
must be >=1
* @throws PINException with the following reason codes:
*
* PINException.ILLEGAL_VALUE
if tryLimit
parameter is less than 1.
* PINException.ILLEGAL_VALUE
if maxPINSize
parameter is less than 1.
*
*/
public OwnerPIN(byte tryLimit, byte maxPINSize)
throws PINException {
if (tryLimit < 1 || maxPINSize < 1) {
PINException.throwIt(PINException.ILLEGAL_VALUE);
}
pinValue = new byte[maxPINSize];
pinSize = maxPINSize;
this.maxPINSize = maxPINSize;
this.tryLimit = tryLimit;
triesLeft = new byte[1];
resetTriesRemaining();
flags = JCSystem.makeTransientBooleanArray((short) 1, JCSystem.CLEAR_ON_RESET);
setValidatedFlag(false);
}
/**
* This protected method returns the validated flag.
* This method is intended for subclass of this OwnerPIN
to access or
* override the internal PIN state of the OwnerPIN
.
* @return the boolean state of the PIN validated flag
*/
protected boolean getValidatedFlag() {
return flags[0];
}
/**
* This protected method sets the value of the validated flag.
* This method is intended for subclass of this OwnerPIN
to control or
* override the internal PIN state of the OwnerPIN
.
* @param value the new value for the validated flag
*/
protected void setValidatedFlag(boolean value) {
flags[0] = value;
}
/**
* !!! CHECK
* This internal method resets tries counter
*/
private void resetTriesRemaining() {
Util.arrayFillNonAtomic(triesLeft, (short) 0, (short) 1, tryLimit);
}
/**
* !!! CHECK
* This internal method decrement tries counter
*/
private void decrementTriesRemaining() {
Util.arrayFillNonAtomic(triesLeft, (short) 0, (short) 1, (byte) (triesLeft[0] - 1));
}
/**
* Returns the number of times remaining that an incorrect PIN can
* be presented before the PIN
is blocked.
* @return the number of times remaining
*/
public byte getTriesRemaining() {
return triesLeft[0];
}
/**
* Compares pin
against the PIN value. If they match and the
* PIN
is not blocked, it sets the validated flag
* and resets the try counter to its maximum. If it does not match,
* it decrements the try counter and, if the counter has reached
* zero, blocks the PIN
. Even if a transaction is in progress, update of
* internal state - the try counter, the validated flag, and the blocking state,
* shall not participate in the transaction.
*
* Note:
* - If
NullPointerException
or ArrayIndexOutOfBoundsException
is
* thrown, the validated flag must be set to false, the try counter must be decremented
* and, the PIN
blocked if the counter reaches zero.
* - If
offset
or length
parameter
* is negative an ArrayIndexOutOfBoundsException
exception is thrown.
* - If
offset+length
is greater than pin.length
, the length
* of the pin
array, an ArrayIndexOutOfBoundsException
exception is thrown.
* - If
pin
parameter is null
* a NullPointerException
exception is thrown.
* @param pin the byte array containing the PIN value being checked
* @param offset the starting offset in the pin
array
* @param length the length of pin
* @return true
if the PIN value matches; false
otherwise
* @throws ArrayIndexOutOfBoundsException if the check operation would cause access of data outside array bounds.
* @throws NullPointerException if pin
is null
*/
public boolean check(byte pin[], short offset, byte length)
throws ArrayIndexOutOfBoundsException, NullPointerException {
boolean noMoreTries = false;
setValidatedFlag(false);
if (getTriesRemaining() == 0) {
noMoreTries = true;
} else {
decrementTriesRemaining();
}
if (length > 0) {
byte tester = pin[(short) ((offset + length) - 1)];
if (length != pinSize || noMoreTries) {
return false;
}
}
if (Util.arrayCompare(pin, offset, pinValue, (short) 0, length) == 0 && length == pinSize) {
setValidatedFlag(true);
resetTriesRemaining();
return true;
} else {
return false;
}
}
/**
* Returns true
if a valid PIN has been presented since the last
* card reset or last call to reset()
.
* @return true
if validated; false
otherwise
*/
public boolean isValidated() {
return getValidatedFlag();
}
/**
* If the validated flag is set, this method resets the validated flag and
* resets the PIN
try counter to the value of the PIN
try limit.
* Even if a transaction is in progress, update of
* internal state - the try counter, the validated flag, and the blocking state,
* shall not participate in the transaction.
* If the validated flag is not set, this method does nothing.
*/
public void reset() {
if (isValidated()) {
resetAndUnblock();
}
}
/**
* This method sets a new value for the PIN and resets the PIN
try
* counter to the value of the PIN
try limit. It also resets the validated flag.
* This method copies the input pin parameter into an internal representation. If a transaction is
* in progress, the new pin and try counter update must be conditional i.e
* the copy operation must use the transaction facility.
* @param pin the byte array containing the new PIN value
* @param offset the starting offset in the pin array
* @param length he length of the new PIN
* @throws PINException with the following reason codes:
*
* PINException.ILLEGAL_VALUE
if length is greater than configured maximum PIN size.
*
*/
public void update(byte pin[], short offset, byte length)
throws PINException {
if (length > maxPINSize) {
PINException.throwIt(PINException.ILLEGAL_VALUE);
}
Util.arrayCopy(pin, offset, pinValue, (short) 0, length);
pinSize = length;
triesLeft[0] = tryLimit;
setValidatedFlag(false);
}
/**
* This method resets the validated flag and
* resets the PIN
try counter to the value of the PIN
try limit.
* Even if a transaction is in progress, update of
* internal state - the try counter, the validated flag, and the blocking state,
* shall not participate in the transaction.
* This method is used by the owner to re-enable the blocked PIN
.
*/
public void resetAndUnblock() {
resetTriesRemaining();
setValidatedFlag(false);
}
}