OCF 1.2 has been made available to the members of the OpenCard Technical workgroup today. The technical members will now evaluate this release candidate for its quality and compliance with the submitted RFCs. The planned public availability is January 2000. Below is a summary of the changes. I also attach the full changes.HTML file. Changes Visible for Application Developers ====================================== OCF Installer Application Management Internal and External Authentication Card Holder Verification OCF for Embeded Devices OCF Support for Java Cards OCF Support for Database cards API Streamlining Bug Fixes Changes Visible for CardService Developers ======================================= Bug Fixes Changes Visible for CardTerminal Developers ======================================== Terminal Locking Bug Fixes (See attached file: Changes.html) Peter Bendel, Smartcard Solutions, Tel.: +49-7031-16-4650, Fax -4888 Dept. 4969, Bldg. 7103-01, Room 01-109 Lotus Notes: bed@ibmde IBM Pervasive Computing Division Internet: [EMAIL PROTECTED] Please visit the OpenCard Framework's homepage at http://www.opencard.orgTitle: OCF 1.1 News
Base OCF Reference Implementation Changes for OCF version 1.1 Changes of OCF version 1.1.1
Configuration OpenCard Home
News and Changes in OCF 1.2
Changes
This section gives an overview of the changes OCF has undergone from version 1.1.1 to 1.2. The changes that have been implemented are mostly changes which result from Requests for Comments (RFC) elaborated by the members of the OpenCard Consortium.Changes Visible for Application Developers
OCF InstallerApplication Management
Internal and External Authentication
Card Holder Verification
OCF for Embeded Devices
OCF Support for Java Cards
API Streamlining
Bug Fixes
Changes Visible for CardService Developers
Bug Fixes
Changes Visible for CardTerminal Developers
Change Details
OCF Installer
OCF 1.2 provides an easy to use OCF Installer package that provides developers with a quick way to get started with OpenCard development. This package consists of a single Java class file that contains all OCF components that were previously provided in the Convenience.zip file plus the full OpenCard API documentation and the OCF Programer's Guide. A graphical installation process guides the user through the configuration of the OpenCard Framework according to the installed hard- and software. On Microsoft Windows 9x/NT an OpenCard folder is added to the startup menu that contains links to available documentation and a few demo programs. To use the OpenCard Framework a working installation of CardTerminal classes provided by the card reader manufacturer and Sun's Java Communications API need to be installed. The OCF Installer package has been tested on Microsoft Windows 95/98/NT. To run it you need JDK version 1.1 or higher.
Application Management
The Application and Card Management Card Service has been entirely changed
and enhanced for OCF 1.2.
The base classes for describing and managing applets are moved from the pacakage opencard.opt.management to the package opencard.opt.applet.
The term "applet" as we use it in this documentation can be either a
program, which is executed on the card itself (like a typical Java Card
applet). Or it can be an application specific set of files and directory
structures (as we will find on ISO compliant file system oriented cards).
In both cases an AppletID is used to identify the applet in a
world-wide unique way. There are standards which define how each smart
card should hold a directory of AppletIDs, allowing any card-external
application to decide, if it supports a particular card or not. Card-resident
applets are described by meta-information encapsulated in AppletInfo
objects.
This meta-information includes
- the user-friendly label,
- the AppletID and
- the SecurityDomain to which the applet belongs.
In the package opencard.opt.applet a very primitive CardService named BasicAppletCardService is introduced, which is only able to select a specific applet on a card.
The two Application and Card Management Card Service known from OCF
1.1.1 are renamed in OCF 1.2 as AppletAccessCardService and AppletManagerCardService.
Both are defined in the package opencard.opt.applet.mgmt. Their
functionality has been changed slightly:
The AppletAccessCardService includes the methods
- list(),
- exists() and
- getInfo().
- installApplet(),
- registerApplet() and
- removeApplet().
It is intended that the AppletInfo class can be extended and that new features/types of information can be added for specific domains (e.g. JavaCardAppletInfo, placed in the package opencard.opt.javacard.mgmt).
A new abstract class named AppletCode is introduced. This class models the actual code of a card applet to be installed in the card. It can be constructed either by specifying a file name that is supposed to contain the code, or giving all bytes of the code in parameter. This class is the generic type that is passed as parameter to an install method. As in the previous case, it is intended that subclasses can be defined, with new features and/or different ways of reading a file to get the actual applet code.
Internal and External Authentication
In OCF version 1.1, the general assumption about access conditions that
have to be satisfied is that an application should not have to worry about.
The implementation of the FileAccessCardService for IBM's MFC
smartcards, for example, deals with external authentication transparently,
provided that the application passed appropriate credentials to the service
before using it.
One drawback of this approach is that an application has no control about the access conditions that are satisfied. Internal authentication is not supported at all, since it is not an access condition enforced by the smartcard. The credentials that have been provided to a service are used at the service's discretion, and the application has little or no control of what the service does with them.
There may be applications that require more control of the security features as is provided in OCF 1.1.1. These applications should be given a way to perform external and internal authentication explicitly. Also, applications should be able to undo an achieved external authentication. By defining a card service for this purpose, applications can take control of the security features using this service. Applications that do not need this control may still rely on the transparent mechanism.
- Key Referencing
- Interface Details
ISO 7816-4 specifies two commands for authentication, INTERNAL AUTHENTICATE and EXTERNAL AUTHENTICATE. The latter is used to satisfy access conditions that may be imposed by the smartcard, it therefore authenticates the external world to the card. The other one is the reverse operation, it authenticates the card to the external world.
In both cases, authentication is based on the knowledge of a secret. This can be either a secret key, using a symmetric cryptographic algorithm, or a private key in the case of an asymmetric algorithm. The authenticating party (challenger) has to know either the same secret key or the matching public key.
The party to be authenticated receives a random challenge, encrypts it with the secret and sends the result back to the challenger. The challenger uses the same key (in the case of a symmetric algorithm) or the matching public key (in the case of an asymmetric algorithm) to verify that the secret is know to it's partner.
For external authentication, the smartcard needs information about the key (secret or public) to be used for verifying the outside world's knowledge of the secret. For internal authentication, the smartcard needs information about the secret for which to prove the knowledge. In OCF 1.1 CardService interfaces, only the CardServices in opencard.opt.signature explicitly reference keys, using interfaces defined in opencard.opt.security. The CardServices in opencard.opt.signature deal with asymmetric cryptography, and the key referencing interfaces cover only public and private keys. No provisions are made for referencing symmetric, secret keys.
For the sake of consistency, an interface for authentication should use a key referencing mechanism similar to that used in opencard.opt.signature. To allow for referencing secret keys, a new interface SecretKeyRef has to be introduced in opencard.opt.security. To allow the definition of a single interface for authentication, regardless of the symmetricity of the underlying cryptographic algorithm, a common base interface for all three kinds of keys has to be introduced, resulting in the following inheritance tree:
KeyRef (new)
|
+--- PublicKeyRef (exists)
|
+--- PrivateKeyRef (exists)
|
+--- SecretKeyRef (new)
This relationship can be duplicated in the default implementations of
the interfaces, also provided by OCF 1.1 in opencard.opt.security.
This requires introduction of new classes KeyFile and SecretKeyFile,
as well as changes to the existing classes PublicKeyFile and PrivateKeyFile.
These changes can be implemented in a compatible way.
For external authentication, a challenge has to be obtained from the card and sent back encrypted. The result is checked by the card. The secret can be easily encapsulated by the existing interface SignCredential in the package opencard.opt.security, although the descriptive comments have to be adapted to asymmetric algorithms, where the length of the random challenge does not have to match the block size of the key. In addition to the credential, a reference to the respective key on the smartcard has to be passed.
For internal authentication, a challenge has to be given to the smartcard. The encrypted challenge has to be checked, either in software or by using a Secure Access Module (SAM) or backend host system. The result of the internal authentication is a boolean value that specifies whether the card is in posession of the secret in question or not. Using a credential here is not appropriate, since the interpretation of the smartcard's response cannot be the responsibility of the CardService. Internal authentication is performed to verify that the smartcard can be trusted. The implementation of the CardService for internal authentication has been selected by OCF to match the inserted card, so it cannot yet be trusted either. The application has to be sure that the final, boolean result has not been forged by an entity associated with the yet untrusted card.
When passing a credential, the application would have to query from the credential whether the internal authentication was successful. This means that the credential is used as a callback mechanism by the CardService as well as directly by the application. This complex usage pattern neutralizes the ease of use achieved by credentials in other places.
Instead, this RFC proposes a lower level interface for internal authentication, where the random challenge is passed in as a byte array, and the encrypted response is returned as another byte array. The application may still use a credential for obtaining the challenge and verifying the response, but the role as a mediator between the SAM or backend and the card becomes more obvious.
There is the question of the length of the random challenge. For symmetric algorithms, the block size is usually 8 bytes. For asymmetric algorithms, challenges of various, larger sizes may be acceptable, since these algorithms use larger block sizes and the challenge will be padded to the appropriate length. Security can be improved by providing a challenge that is larger than 8 byte. A method to query the required length for the challenge is needed anyway, in case an algorithm does not accept an 8 byte challenge, or a SAM enforces a larger challenge. That method has to return the block size in the case of a symmetric algorithm, and should return the maximum allowed length of the challenge for an asymmetric one. In both cases, the application can be sure that the smartcard will be able to handle a challenge of the length returned by that method.
External authentication, like Card Holder Verification, is used to satisfy access conditions imposed by the smartcard. In consequence, an application will also want to reset these access conditions when it is finished. The respective method will have to reset external authentications, but may as well reset Card Holder Verifications and other access conditions. Since it will typically be called by an application when the smartcard is no longer needed, this behavior will not cause problems. However, the name of the method should not mention authentication or keys, to avoid confusion with the application programmers, and to avoid implementations of the same functionality under different names with CardService implementors.
Card Holder Verification
In OCF version 1.1, the general assumption about access conditions that
have to be satisfied is that an application should not have to worry about.
The implementation of the FileAccessCardService for IBM's MFC smartcards,
for example, deals with Card Holder Verification without any involvement
of the applications using it.
One drawback of this approach is that an application has no control about which Card Holder Verifications are performed at what time. For example, it is generally not possible to check whether the user has already been prompted for a password. Also, it is not possible to simply enforce card holder verification at application startup, or to reset the card holder verification when the application is done with the card. There may be applications that require more control of the Card Holder Verification as is currently provided. These applications should be given a way to perform card holder verification explicitly. Also, applications should be able to undo a successful card holder verification.
By defining a card service for this purpose, applications can take control of the card holder verification. Applications that do not need this control may still rely on the transparent mechanism, as long as the CardService to be used supports it.
The transparent mechanism for Card Holder Verification may still be useful. However, it's use is severly restricted by the definition of the interface opencard.core.service.CHVDialog, which returns a String holding the password or PIN. The card channel that evaluates this String can only apply a default conversion and paste the resulting byte array into a prepared command APDU. This is appropriate only for alphanumeric passwords in the locale of the Java environment in which the OpenCard Framework is running. It also assumes that the password has to be presented in plain format, not with secure messaging.
Performing Card Holder Verification is a complex task with multiple dependencies. Requesting the password from the card holder depends on the hardware that is available. For example, a screen dialog may be popped up, or an attached card reader's display and pinpad can be used. The command or commands to verify the password depend on the card OS. Length, encoding, padding, and the range of valid characters depend on the application and on the card layout. When specifying a CardService for Card Holder Verification, it has to be decided which of these dependencies shall be handled by the CardService, and which will have to be dealt with by the applications. There is no one, perfect solution to this problem.
Specifying a CardService at this level of abstraction does not rule outthe specification of other CardServices, performing the same task at a higher level of abstraction. There may still be CardServices for Card Holder Verification that do convert a string presented by an application to an encoding appropriate for the card.
A CardService for Card Holder Verification obviously needs a method
that performs Card Holder Verification with the smartcard. Typical file
system based SmartCards, like the German GeldKarte, support different passwords
for subtrees of the file system, and also multiple passwords within the
same subtree. On JavaCards, each applet may specify it's own set of passwords,
too. Parameters to the verification method have to indicate the subtree
or applet as well as the password within that subtree.
To specify the subtree on a file system card or the applet on a JavaCard,
the tag interface opencard.opt.security.SecurityDomain can be
used. It is implemented by class opencard.opt.iso.fs.CardFilePath,
and may in the future be implemented by classes that identify security
domains in other cards.
To specify the password within a security domain, a simple integer
should be sufficient. The GeldKarte, already mentioned above as an example,
supports passwords 0 and 1, IBM's MFC smartcards passwords 1 and 2, Gemplus'
GPK cards passwords 0 to 7. Although all these are file system based cards,
it seems likely that an integer allows to distinguish the passwords on
other cards, too.
The third argument to the password verification method is the password
itself. It should be passed as a byte array, giving the application full
control of the encoding of the password. To use a protected PIN path, in
which the application does not get to know the password at all, null can
be passed instead. In this case, it is the service's responsibility to
query the password, to encode it, and to prepare an appropriate APDU to
send to the smartcard. If the terminal supports it, this responsibility
may be delegated to it. Using a protected PIN path prevents the application
from specifying an encoding for the password, but that problem is inherent
in the concept of a protected PIN path. If the password has to be presented
to the card using secure messaging, it is the service's responsibility
to perform the required cryptographic operations. The return value for
performing Card Holder Verification is a boolean that indicates whether
the password was correct or not. Since the return value is generated by
the CardService, it can only be trusted if the CardService is trusted.
Passing the password as a byte array leaves the question of the length
of the byte array. File system based, ISO 7816-4 compliant smartcards have
a password length of 8 byte. However, considering JavaCard and the flexibility
of applets, other password lengths may also occur. To allow the application
to prepare a byte array of appropriate length, there should be a method
to query the required length. For ISO cards, this method can simply be
implemented to return a constant 8, causing minimal overhead.
Other properties of the password, for example the encoding and padding
rules, can be rather complex and may depend on application data that is
not accessible to the CardService.
If the application is able to perform Card Holder Verification explicitly,
thereby satisfying access conditions for data on the card, it should also
be able to reset those access conditions. On file system based smartcards,
this can typically be done by a SELECT operation that leaves the directory
on the smartcard. Even if this is not possible, a reset of the smartcard
can clear access conditions. Either way, all access conditions for the
respective subtree of the file system or, in general, the security domain,
are invalidated at once. The method does therefore not require a password
number as an argument, the security domain is sufficient.
- Change in Interface opencard.core.service.CHVDialog
OpenCard Framework implements features for a protected PIN path, in which neither the terminal or host application nor the CardService get to know the PIN. If a CardTerminal implements this feature, that implementation is used. Otherwise, a default replacement in opencard.core.service gets invoked. The default replacement uses a GUI dialog to query for the password, then converts the string to a byte array, and pastes it into an APDU that has been prepared by a CardService. The GUI dialog can be replaced by the application, which may be used to inform the user of the security domain for which the password is required.
There are several steps in processing a PIN. The string entered by the user must be encoded into a byte array, padded to the appropriate length, packed into a command APDU and finally sent to the card, which may involve secure messaging. In the default implementation, the encoding is done in a predefined way in opencard.core.service, the padding is implicitly done by the CardService that prepares the APDU, and secure messaging is not supported at all. The flexibility of this approach can be considerably enhanced by encoding the PIN within the GUI dialog and returning a byte array instead of the string. The default GUI can be implemented to achieve the same behavior as before, but the applications would be free to implement replacement GUIs that use other kinds of encoding, for example BCD. The fact that the application thereby gets access to the PIN that is entered does not weaken the security, since the currently supported application-defined GUIs can do the same.
While the responsibility for encoding and padding are transferred to the application by this change, secure messaging is still not supported. There is no need to overload the OpenCard Framework with support for features that are rarely used.
To implement this change, the method defined in interface CHVDialog was changed from
public String getCHV(int chvNumber);
to
public byte[] getPassword(int chvNumber, int length);
Java Card support
OpenCard Framework 1.1 only defines interfaces and access methods for file
system oriented cards. The only support for JavaCards in OCF1.1 is an interface
named JavaCardCardService in the package opencard.opt.javacard. This interface
only declares a method that sends a given APDU to a given applet.
When programming proxy classes for JavaCard applets, some base classes providing generic functionality needed by concrete proxy classes are helpful. These classes provide basic functions like sending a particular APDU to a particular applet on the card. Furthermore, they support the programmer of proxy classes for applets in the complex state handling of applet states.
OpenCard 1.2 supports JavaCards that meet the objectives mentioned above.
The following classes and interfaces are added to the package opencard.opt.javacard:
- BasicJavaCardService - This class implements the basic functionality needed to communicate with applets on a JavaCard. It provides send-methods in three versions:
- JavaCardState - This class represents the state of the JavaCard, i.e. the currently selected applet. The state information allows the BasicJavaCardService to send select-APDUs only when necessary, i.e. only when an APDU shall be sent to an applet other than the currently selected applet.
- AppletProxy - This class is derived from the class BasicJavaCardService. It adds an attribute that holds the application identifier of the applet to which the applet proxy is associated. It provides methods similar to those of the base class, except that the application identifier parameter is not required because every AppletProxy implicitly knows the application identifier of the associated applet.
- AppletState - This class is an abstract base class from which concrete AppletState implementations can be derived. It declares an abstract method named appletDeselected() that can be called from the BasicJavaCardService when selecting another applet. The purpose of this method is to reset parts of the state that become invalid as a result of applet deselection.
The first sends a given command APDU to a given applet on the card, the second sends a given command APDU to a given applet on the card using a preallocated card channel provided by the calling method of the derived class, and the third sends a verify CHV command APDU to the JavaCard after filling in the password obtained from the CHV dialog associated with the BasicJavaCardService.
Terminal Locking
OCF 1.1 provides no means for locking a terminal or individual slots. These
features are added to OCF 1.2 without changing the basic design of OCF
and without breaking any existing code. Entire CardTerminal objects as
well as individual slots can be locked and unlocked. Consistent behavior
of the card service layer is assured. The right to use a locked terminal
is bound to the thread that has locked the terminal
The Terminal Locking mechanism is based on four requirements we see for a card terminal and slot locking mechanism:
- When no locking is required, the behavior of OCF shall be unchanged. OCF Programs that need no locking shall run without change.
- When a card terminal or slot is locked, only the owner of the lock shall be able to use the terminal or slot.
- The service layer must respect the locking mechanism, i.e.when a slot is locked, SmartCard objects may only be created for the owner of the lock.
- The locking methods should not be a mandatory part of the CardTerminal interface, but form a separate, optional interface to be implemented by lockable card terminals.
- API Modifications
- Implementation
- Convenience class AbstractLockableTerminal
- internalLock(), internalLockSlot(slotid) internalUnlock(), internalUnlockSlot(slotid)
- lockableOpenSlotChannel() instead of internalOpenSlotChannel
The OpenCard API has been augmented as follows:
Additional Interface: opencard.opt.terminal.Lockable
public java.lang.Thread lock() throws CardTerminalException
Locks the entire card terminal, including all slots as well as pin
pad and display if available, returns a reference to the new lock owner
on success, else throws a TerminalLockedException.
Alternative: public boolean lock()
Returns true if successfull, false if already locked
public java.lang.Thread lockSlot(int) throws CardTerminalException
Locks the slot with the given slot number, returns a reference to the
new slot owner on success, else throws a TerminalLockedException.
public void unlockSlot(int) throws CardTerminalException
Unlocks the slot with the given slot number.
public void unlock() throws CardTerminalException
Unlocks the entire card terminal, including all slots as well as pin
pad and display if available.
Additional method for the class SlotChannel:
public Object getSlotOwner()
Gets the current slot owner of the associated slot. Required by the
CardServiceRegistry to determine whether a given thread may obtain
a SmartCard object for the card in the associated slot or not.
The type of the slot owner is Object instead of Thread to avoid a dependence
of the opencard.core.terminal package on threads.
Additional exception: opencard.opt.terminal.TerminalLockedException extends opencard.core.terminal.CardTerminalException
Change constructor of SlotChannel:
in addition to public SlotChannel(CardTerminal terminal, int slotID)
SlotChannel(CardTerminal terminal, int slotID, Object slotLockOwner)
A thread can call CardTerminal.lock() to lock a card terminal and all of its slots and CardTerminal.unlock() to return ownership of the lock. The lock() method can only be called successfully when the card terminal has no slot channels open and no other thread has locked a slot. The lock() call also prevents other threads from using the pin pad and display of the card terminal and from sending terminal commands.
A thread can call CardTerminal.lockSlot() to lock a particular slot and CardTerminal.unlockSlot() to return ownership of the lock. The lockSlot() method can only be called successfully when there is no open SlotChannel for the slot to be locked.
The CardTerminal class has a reference to the thread that currently has the lock (lockOwner). If this reference is not null, it is locked. If the reference lockOwner is null, the terminal is free.
In addition, for each slot number, the CardTerminal holds a reference to the thread that currently owns the terminal's slot. If the reference is not null, slot i is locked. If the reference is null, the slot is free.
CardTerminal objects give out SlotChannels to arbitrary threads only if lockOwner is null and the relevant slotOwner entry is null. While these references refer to a thread, SlotChannels are only given to that thread.
Note that this does not prevent a lock owner from deliberately or accidentially passing the SlotChannel reference to another thread.
The SlotChannel class has slotOwner reference that identifies the owner. This reference is set at creation of a SlotChannel object and does not change within its lifetime. The reference slotOwner is null if the associated slot has not been locked or refers to the owner if the associated slot has been locked.
When the CardTerminal's unlock() method is called, all open SlotChannels are closed.
The CardServiceRegistry singleton returns a SmartCard object for a smart card in a slot associated with a particular SlotChannel to arbitrary threads only if the slotOwner reference of the associated SlotChannel object is null. If there is a lock owner, the CardServiceRegistry creates SmartCard objects only for the lock owner. Thus, only the thread that called CardTerminal.lock() can obtain a SmartCard object for a card in a locked reader.
If a multithreaded application needs access to a locked terminal from multiple threads the SmartCard object can be passed from the thread that has locked the terminal to the other threads. Thus the SmartCard object plays the role of a gate object at the card service layer as the SlotChannel plays the role of the gate object at the card terminal layer
The OCF 1.1 implementation of SmartCard.waitForCard() used the CardWaiter to wait for a card. The CardWaiter is a CardTerminal event listener which creates a SmartCard instance in the CardTerminalRegistry polling thread. Since the polling thread is not allowed to allocate a SlotChannel on a locked terminal this code has been changed as follows:
When a card inserted event is received by the card waiter it must notify the waiting thread and the waiting thread must then try to obtain the SmartCard object. If the card inserted does not match the card request the CardWaiter must then continue to wait for card insertion events. Thus the call to allocate the SlotChannel is moved from the polling thread to the thread actually waiting for the card, which has the right to access the locked terminal.
The implementation details described above are security sensitive. To avoid that each card terminal implementor has to deal with the complexity of security implications a new class opencard.opt.AbstractLockableTerminal is introduced which handles most of the locking specific processing.
Implementers of lockable Terminals would then subclass AbstractLockableTerminal and implement the methods
API Streamlining
The changes for the API Steamlining bring a number of minor changes to
the OpenCard Framework which are meant to make the API simpler, and implementations
smaller.
- Removal of Deprecated Features:
- Removal of Dual APIs
A number of features are already deprecated in OCF 1.1.1. Some of these are removed for OCF 1.2. Here is a list of the deprecated features:
opencard.core.event.CardTerminalEvent:
Supports events that indicate addition and removal of card terminals.
This was required in OCF in pre-1.0 releases, when listener for card terminal
events were registered directly at all card terminals. The listeners had
to be aware of the fact that a new card terminal was added, so they could
register for the new terminal's events. In the meantime, listeners for
card terminal events, that is for events that indicate card insertion or
removal, are tracked in the card terminal registry. Events are no longer
broadcasted directly by the card terminals, but given to the card terminal
registry, which distributes them to the registered listeners. A listener
will now get the events from newly added card terminals automatically.
The events that indicate changes in the set of card terminals are therefore
obsolete and should be moved. The CardTerminalEvent class contains
some more deprecated methods that are related to the the int/Slot duality
addressed below. These methods can not be removed, but must be un-deprecated
instead.
opencard.core.event.CTRListener
Interface for listeners to events that indicate added or removed card
terminals. As pointed out before, the events for added and removed card
terminals are obsolete.
opencard.core.terminal.CardTerminal
Contains methods for adding and removing listeners at the terminal.
The events listened to indicate card insertion and removal. As pointed
out before, these events are now distributed via the card terminal registry,
and filtering for events from particular card terminals is easy. Direct
registering at a card terminal is therefore obsolete, the respective methods
are removed.
opencard.core.terminal.CardTerminalRegistry
Contains methods for broadcasting events that indicate added and removed
card terminals, and for registering listeners to these events. As pointed
out before, this feature is obsolete and the respective methods are removed.
opencard.core.service.SmartCard
Contains methods for registering listeners to events that indicate
card insertion and removal. These are convenience methods that are identical
to the respective ones in the card terminal registry. They are removed.
opencard.opt.signature.SignatureCardService
Contains the methods from the anachronistic version of this interface.
Every implementor of the SignatureCardService currently has to
implement these methods as dummies that throw an exception. They are also
removed.
In the packages opencard.core.terminal and opencard.core.event, there is a duality in the usage of int values and Slot objects, respectively, to identify a card terminal's slots. In implementations of card terminals, only int values are used. Slot objects are mapped to int values in the base class. This duality is an anachronistic feature left over from pre-1.0 versions of OCF. Originally, the Slot class provided features for example to communicate with that card. All these features have been moved to the class SlotChannel, leaving the Slot class basically meaningless. Apart from the internal operation of the OCF core, it is used only in events that indicate card insertion and removal to specify the source of the event. Replacing the Slot objects in these events by an int value is simple, since the card terminal for which the slot number is valid is stored explicitly in the event, anyway. The class opencard.core.terminal.Slot is deprecated, and removed in a future release of OCF. Likewise, all methods that relate to Slot objects, especially in the class opencard.core.terminal.CardTerminal, are deprecated and later on removed, since the dual methods using int values can be used instead. The class opencard.core.event.CardTerminalEvent is extended by a method that returns the originating slot as an int value, and the methods and constructors referring to Slot objects are deprecated. Any other methods that relate to Slot objects in OCF are deprecated. If required, methods that accept int values can be added as replacements.
- Removal of Convenience Methods
- constructor with wait behavior (NEWCARD or ANYCARD), a CardTerminal, and a CardService as arguments. For the terminal and service arguments, null can be passed as a "don't care" value.
- setTimeout, which allows to disable timeout handling without defining a magic number for this purpose
- setFilter, since filtering is a rarely used feature that should not be reflected as a required argument of the only remaining constructor
opencard.core.service.SmartCard.getSmartCard(CardTerminalEvent)
This method is obsolete. There is a method with the same name, taking a CardTerminalEvent and a CardRequest argument. Invoking that method with null for the CardRequest results in the same behavior as invoking the single-argument method. This method therefore is deprecated, and removed in a future OCF release.
opencard.core.service.CardRequest
This class is basically a collection of attributes, which can be used
to specify a filter for cards an application is interested in. Besides
these attributes, it offers an overwhelming number of constructors that
accept various subsets of the attributes as parameters, and set/get methods
for the attributes. Interestingly, the constructor that would have been
used most often in IBM code samples (package demos.samples), that
is one that takes NEWCARD/ANYCARD as it's single argument, is not available
since it's method signature would be the same as the one taking a timeout
argument.
Most of the currently provided constructors and setXXX-methods are
deprecated. Instead, only the following new constructor and setXXX-methods
are provided:
- Removal of Obsolete Features
The class opencard.core.service.CardServiceScheduler supports customized card channels, that can be provided by a card service factory. This feature was probably used only by the IBM MFC card services and is obsolete, since the problems solved with it can now be solved using the default card channel's setState/getState methods. The support for customized card channels in the scheduler, that is methods setCustomChannel, useDefaultChannel, and isCustomized should be deprecated and removed in a future release of OCF.
The class opencard.core.terminal.CardTerminal defines an abstract method named internalFeatures. In most implementations, this method just returns it's argument. Instead of requiring every card terminal implementation to define this method empty, this should be the default implementation in the base class. Card terminals that specify internal features can still override the methods, others can ignore it.
- Removal of Unimplemented Features
The class opencard.core.terminal.CardTerminal provides several methods that take a timeout as an argument, either required or optional. Timeout handling, however, has never been implemented in a satisfactory way. Actually, PC/SC does not provide means to change timeout values, so the PC/SC wrapper terminal implementation has no chance to implement timeout handling. In consequence, timeouts should be removed from the terminal layer API. The API of the service layer is not affected by this change, since it does not support terminal layer timeouts. In the terminal layer, the classes Slot, SlotChannel, CardTerminal, and the interface VerifiedAPDUInterface are affected. In the classes Slot and SlotChannel, the methods getCardID and sendAPDU with timeout argument are simply deprecated. In VerifiedAPDUInterface, the method sendVerifiedAPDU with timeout argument is deprecated, and a default implementation calling the method without timeout is added to class CardTerminal, so implementing that interface does not require to implement a deprecated method. In class CardTerminal, the following methods are affected:
| Method | abstract | with timeout | w/o timeout |
| getCardID | yes | yes | yes |
| internalReset | yes | yes | no |
| internalSendAPDU | yes | yes | no |
| reset | no | yes | no |
Of these methods, only getCardID and reset are publicly visible. To minimize the changes for existing card terminal implementations, the following changes are made:That way, the API to be implemented by new terminals is a subset of the API that currently has to be implemented. Existing card terminal implementations can still be used, provided they are able to deal with the default timeout values that are substituted for the actual arguments. By deprecating the timeout features of the public terminal API, application programmers are aware of the fact that timeouts are not supported. The deprecated methods will be removed in a future release of OCF.
- getCardID with timeout argument was deprecated, and a default implementation that invokes getCardID without timeout was provided. The default implementation is required so that new card terminal implementations need not define a deprecated method.
- the reset method with timeout argument was deprecated. A reset method without timeout argument was provided instead.
Changes for Reduced Package Dependencies
In OCF1.1.1, the packages opencard.core.terminal and opencard.core.event are recursively dependent on each other. The classes in the terminal package deal with event handling, and therefore depend on the event package. On the other hand, the class CardTerminalEvent in the event package stores the event source, that is a reference to a card terminal, and therefore depends on the terminal package. As the name suggests, the package opencard.core.event should deal with events in OpenCard. To achieve this, a variety of changes are required. All changes are made in a way such that current implementations of card terminals can still be used with deprecated methods. The recursive dependency between the packages, however, will remain until the deprecated methods are removed in a future release of OCF.
- The primary action to move the event handling to the event package
was to introduce a class opencard.core.event.EventGenerator which
takes the following responsibilities from the CardTerminalRegistry:
- track the pollable terminals
- define the polling thread
- generate the detected events
- track the event listeners
- distribute the generated events
- updateCards(terminal, slot, inout)
- updateTerminals(terminal, addrem)
- Changes to the Behavior
- Extension for Versioning
Invoked when a card is inserted or removed. The terminal and slot argu ments specify the event source, the inout boolean value indicates insertion or removal.
Invoked when a card terminal is added or removed. The terminal argument indicates the terminal affected, the addrem boolean value indicates that the terminal has been added or removed, respectively. Unfortunately, it is not possible to deal with event listeners in the same way. The interface CTListener is defined in the event package, so all references to it was removed from the terminal package.
The class opencard.core.service.CardServiceScheduler implemented it's own queueing mechanism, which required two inner classes for a queue and it's elements. By relying on the respective JVM's queueing mechanism, which is accessible through the methods java.lang.Object.{wait|notify}, the complexity and size of CardServiceScheduler is dramatically reduced.
It has been discussed several times to have an OCF feature to obtain version information. Since Java 2, with it's builtin versioning via the class java.lang.Package, does not seem to gain acceptance as fast as expected, it seemed still reasonable to introduce a simple version information in OCF. In the class opencard.core.service.SmartCard, the method public static String getVersion() was introduced. It returns a string of the form "OCF1.2;IBM Reference Implementation, Build Hudson, 21-May-1999". The first part indicates the API. It always starts with "OCF", followed by an API version number, and terminates by a semicolon. Currently, this API version number is simply the OCF release number. When a formal OCF specification becomes available, it would refer to the version of that specification it implements. After the semicolon, vendor specific information is included. The format of the vendor specific information is not specified.
Bug Fixes
- New CardID constructor:
The CardID constructor so far assumed that the TCK byte in the ATR was always present. The last byte is not a historical byte, but the check character TCK as defined in ISO 7816-3 6.4 and 6.4.3.
"The value of TCK shall be such that the exclusive-oring of all bytes
from T0 to TCK included is null"
...
"If only T=0 is indicated, TCK shall not be sent. In all other cases,
TCK shall be sent".
opencard.core.CardID did not correctly respect this. It always assumed the presence of byte TCK. The right way to do this is to parse the ATR from the beginning (counting which interface characters are present) instead of counting from the back end.
- Problem in CardHolderVerificationGui
We removed the following variable which was never used
private static String BACKGROUND = System.getProperty(OpenCardConstants.OPENCARD_PROPERTY + "UserInteraction.image", "ZueriLab.gif");
and did not work correctly in native browser support.
- Additional constructor in RSAPrivateKey
opencard.opt.security.RSAPrivateKey only had a constructor from byte arrays but not from java.math.BigInteger which was inconvenient in many cases.
The following cinstructor was added:
public RSAPrivateKey(BigInteger e, BigInteger m)
- Bug fix in constructor of opencard.opt.security.DESKey:
- Typo in OCF11CardServiceFactory:
- Bug with long APDUs in opencard.opt.terminal.protocol:
The DESKey constructor did not copy the byte array passed as argument. If the caller changed/reused her byte array the DESKey got affected.
We had a bug in opencard.opt.service.OCF11CardServiceFactory. We changed the class definition FROM
public abstract class OCF11CardServiceFactory extends CardServiceFactory
{
private Tracer ctracer = new Tracer(CardServiceFactory.class);
TO
public abstract class OCF11CardServiceFactory extends CardServiceFactory
{
private Tracer ctracer = new Tracer(OCF11CardServiceFactory.class);
The opencard.opt.terminal.protocol.T1Block class had a LEN field of type byte. This lead to the problem that response APDUs of longer than 127 bytes caused a timeout exception because the LEN field had a numeric overflow and got negative.
OCF for Embedded Devices
OCF for embedded devices defines a subset of OCF that is suitable for embedded
devices with only one card reader, potentially with several slots. This
subset is implementable on Embedded Java Virtual Machines efficiently
and with small footprint.
OCF for embedded devices has the following properties:
- As compatibile with OCF as possible - Meanwhile, there are several standards and standard proposals that refer to OCF and assume stability of OCF. When additions are made to the OCF API which are also advantageous for OCF for embedded devices, these additions may also be made to OCF for embedded devices.
- No redundant APIs - In OCF, there are redundant APIs: Many methods are available in several versions with different parameter lists. On embedded devices, small footprint is more important than convenience. Therefore, OCF for Embedded Devices defines an API that provides no convnience methods, there is always exactly one method to handle a particular task.
- CardTerminalRegistry: When running on PCs, OCF must potentially handle several readers. Embedded devices have only one reader, potentially with several slots. Therefore, OCF for Embedded uses a CardTerminal singleton representing the single card reader, so that no CardTerminalRegistry is needed for that purpose. The event handling functionality of CardTerminalRegistry is moved to a new class opencard.core.event.EventGenerator.
- The CardTerminalRegistry is moved to the event package in OCF for embedded devices, since after the removal of the registration function, it is only an event generator and multicaster. This makes the terminal layer independent from the event layer. Renaming from "CardTerminalRegistry" to "EventGenerator" makes the semantic of the class clearer and avoids confusion with the still existing CardTerminalRegistry in OCF 1.x.
- No Slot class: In the terminal layer of OCF there is a duality between Slot objects and integers. At the end, each method that takes a Slot object gets the slot number from the Slot object and calls the appropriate method which takes an integer argument instead of a Slot object. OCF for Embedded avoids the integer/Slot duality in OCF for embedded devices by omitting the Slot class.
- No waitForCard() mechanism: In OCF, there are two possibilities for obtaining a SmartCard object: using the event-mechanism or using the waitForCard()-mechanism. The waitForCard()-mechanism is implemented based on the event mechanism and adds considerable footprint. In an event driven program it is never needed and if it should be desired, it could be provided by a utility class that does not need to be part of the core classes. OCF for Embedded devices will not provide the redundant waitForCard()-mechanism.
- No secure PIN path: OCF provides a mechanism that allows to transmit an incomplete VERIFY_PIN command to a reader with a display and PIN pad and let the reader add a PIN entered on its PIN pad by the user. When OCF runs in an embedded device, this functionality is not required, because readers in embedded devices do usually not have their own dedicated display and PIN pad. OCF for Embedded Devices will not provide the classes and interfaces for implementing a protected PIN path.
- No start/shutdown mechanism with automatic registration of CardServiceFactories and CardTerminalFactories listed in a property file: Inside of an embedded device, there is not necessarily a file system. We assume that inside of an embedded device, there is some kind of bootstrap code that is started when the terminal is switched on and this bootstrap code registers the required CardServices explicitly with the CardServiceRegistry. Additional CardServices can be registered by applications when needed.OCF for Embedded Devices does not provide methods for starting and automatically registring services nor for shutting down.
- Independency of card terminal layer: Even though the OCF for Embedded Devices API subset is implemented in very small footprint, there may be applications and devices where it may be useful to use the card terminal layer without the event and service layers. Therefore, OCF for Embedded Devices avoids all dependencies of the card terminal layers to event and card service layers.
News and Changes in OCF 1.1.1
This section gives an overview of the changes OCF has undergone from version 1.1 to 1.1.1 The changes that have been implemented are mostly bug fixes and streamlining of code, but include also some minor design changes which result from Requests for Comments (RFC) elaborated by the members of the OpenCard Consortium.Changes
We assume that there are basically three kinds of developers that use OCF: Application developers, CardService developers, and CardTerminal developers. Below, there are three lists with the major changes that affect each kind of developer. The hyperlinks will lead you to the detailed descriptions of those changes in the next section.Changes Visible for Application Developers
Changes Visible for CardService Developers
Changes Visible for CardTerminal Developers
Change Details
Native Browser support
Deploying OCF in a web browser environment has so far been limited to Sun's java plug-in (also called Activator). OCF 1.1.1 introduces support for the native Java Virtual machines and security concepts of potentially any browser with specific support for Microsoft Explorer and Netscape Navigator. Please see the OCF Programming Guide for instructions how to code/package applets to run under these browsers.The changes introduced for native browser support do not change existing interfaces and are only relevant for developers who want to deploy OCF from an applet running under those browser's JVM.
Changed CardServiceFactory interface
Card service factories can now communicate with the card to determine whether they can instantiate the requested card service. In OCF 1.1 card service factories could only use the CardID (ATR) to determine the type of card. But often the ATR was insufficent to determine whether the card could be supported.New card service factories (subclasses of opencard.core.service.CardServiceFactory) should implement the getCardType() and getClasses() methods.
Existing factories that implement the knows() and cardServiceClasses() methods must now be derived from opencard.opt.service.OCF11CardServiceFactory to compile without errors.
Changed behaviour of SmartCard.waitForCard()
SmartCard.waitForCard() does now block the caller until a card matching the card request is found or until the timeout expires.In OCF 1.1 waitForCard() returned whenever a new card was inserted, regardless whether the card inserted matched the card request. The method returned null when the card did not match the request.
News and Changes in OCF 1.1
This section gives an overview of the changes OCF has undergone from version 1.0 to 1.1. The changes that have been implemented are not restricted to bug fixes, but include a considerable number of design changes.The Rationale tells you why we decided to change the OpenCard API. In Changes, you will find lists of the changes that affect applications, CardServices, and CardTerminals written for OCF 1.0. Detailed descriptions of the major changes are presented in the Details section.
Rationale
Changing a published API in a way that breaks code written against it causes trouble. It does not only require a considerable effort from our side to adapt the reference services and terminals. It also requires effort from your side to adapt your programs to the new API. However, we had good reasons for changing the OCF API. This section is meant to give you an overview on some of these reasons and motivate you to upgrade from OCF 1.0 to 1.1. (We promise not to do it again - unless the consortium members have overwhelming reasons.) The changes we implemented have been guided by the following objectives:Codesize Reduction
Several functions of OCF have been reduced to save code size. The changes were discussed and agreed by the Core Workgroup and the CardService Workgroup of the OpenCard consortium. The policy was to save code that is rarely used and not essential while keeping incompatibility to version 1.0 at a minimum. Version 1.1 of OCF allows to use the terminal layer without the Service layer, which is an option for small systems with memory limitations. In this case the size of the terminal layer (with tracces removed and using the Jikes compiler) is 32 KBytes.We have simplified and split some of the CardService interfaces. This provides a chance for implementing smaller CardServices with support for the most frequently needed functionality of a smartcard. There is an improved layering between other parts of OCF, too. This allows for downsizing by using only the lower layers. Additionally, it simplifies the task of getting started with OCF. A developer can now start by looking at smaller parts of OCF and move to the more complex APIs later.
Performance Tuning
In general, we have modified internal functions and parts of the structure to allow for faster execution and reduced garbage collection overhead.In the CardService area we have introduced a layering for the opt.iso.fs package, where you can chose between highest abstraction and ease of programming or highest execution efficiency. For example, the time we measured for reading the 64 bytes card holder data in the Stockbroker demo was 0.65 seconds using OCF's java.io specializations, 0.52 seconds using CardFile and the file service directly, and 0.46 seconds using CardFilePath and the file service.
We have reduced the tracing information generated. The tracing output was always composed before the tracer decided if the tracelevels required to output it or not. This involved overhead in some functions even if the trace was not used. This overhead was reduced. In addition, the traces can be removed from the code completely using a simple perl script.
We have allowed the reuse of exising objects instead of create/delete cycles. This puts a small additional burdon on the programmer writing a CardService implementation, but is transparent to application programmers. The performance could be improved significantly. For example, by making CardChannel objects reusable, the time for reading data records has been reduced by 69% in one of our test programs, without breaking any code.
We have replaced the OCFEventMulticaster by an implementation that is dramtically faster for a small number of events, like typical OCF setups have. Details
Error Handling
OCF exceptions were not checked in 1.0. This made programming errors possible, where severe errors at runtime were not handled appropriately by the application code. OCF 1.1 has moved to and enforces a stricter control of exception handling, which is more consistent with other Java frameworks. Unfortunately, this change will break existing code that failed to handle OCF exceptions. Details
Documentation Enhancements
The API documentation has been greatly enhanced to provide more information. Especially the CardService interfaces for file access and signature generation have been documented in detail.The Programmer's Guide to OCF has been reworked to reflect all changes implemented in OCF 1.1. The code examples have been reviewed, simplified, and explained in more detail.
Changes
We assume that there are basically three kinds of developers that use OCF: Application developers, CardService developers, and CardTerminal developers. Below, there are three lists with the major changes that affect each kind of developer. The hyperlinks will lead you to the detailed descriptions of those changes in the next section.Changes Visible for Application Developers
- Exceptions are checked.
- CardIDs are simpler.
- Event handling is simpler.
- CardFiles are simpler.
- FileSystemCardService is split.
- SignatureCardService is split.
- Key handling is modified.
Changes Visible for CardService Developers
- Exceptions are checked.
- CardIDs are simpler. This affects CardServiceFactories.
- CommandAPDUs are reusable.
- CardService instantiation is simpler.
- FileSystemCardService is modified.
- SignatureCardService is modified.
- Key handling is modified.
Changes Visible for CardTerminal Developers
Change Details
Checked Exceptions
The exception hierarchy defined in OCF 1.0 has been reviewed and changed. Some obsolete exceptions have been removed, others have been renamed. Finally, seven exceptions have been moved from opencard.core.service to opencard.opt.service.To help programmers in developing error handling code, OpenCardException and all exceptions derived from it are checked now. These exceptions must be caught or declared in the throws clause of method declarations. OpenCardException is a subclass of java.io.IOException, so applications that use the OCF specializations of the java.io package will require only few changes.
CardID
In OCF 1.0, the class opencard.core.terminal.CardID served a dual purpose. It represented a smartcard's ATR, and it could be used as a template for matching a set of ATRs. In order to do this, it included methods that tried to determine the card OS from the ATR. This functionality relied on a particular structure of the ATR, which was not fully specified. It also lead to a lot of confusion about OpenCard compliant ATRs and OpenCard compliant smartcards.In OCF 1.1, the CardID class simply represents a smartcard's
ATR, optionally along with the terminal and slot in which the card has
been inserted. Interpreting the ATR is the responsibility of the available
CardServiceFactories. The notion of OpenCard compliance has been removed
completely. There is no requirement that makes an ATR, or a smartcard,
OpenCard compliant. If there is a CardServiceFactory that recognizes the
ATR, OCF can deal with the smartcard.
For selecting particular ATRs in a CardRequest, the interface
CardIDFilter has been introduced. It can be implemented by an
application in any appropriate fashion. The template functionality of CardID
in OCF 1.0 did not provide this flexibility.
Event Handling
The event handling in opencard.core.terminal has been simplified. All terminal events are now broadcasted via the CardTerminalRegistry. Registering as listener at a CardTerminal is still supported, but deprecated.The registry events that notified applications about CardTerminals that have been dynamically added or removed are no longer available. Since an application gets the events of all CardTerminals via the CardTerminalRegistry, there is no need for them anymore.
The event broadcast is done in a simple loop over a vector of listeners. The class OCFEventMulticaster has been removed. Registering or unregistering listeners at an event multicaster caused considerable overhead, which is now avoided.
APDU classes
The classes APDU, CommandAPDU, and ResponseAPDU have been changed to allow reuse of APDUs. For ResponseAPDU, the majority of the changes is transparent. On the other hand, CommandAPDU has changed considerably. Instead of the various constructors for different ISO cases, there are only constructors to initialize a buffer. The actual APDU is composed by invoking append methods that add bytes or byte arrays to the buffered APDU. Optionally, an APDU can be prepared in a byte array and passed to one of the constructors of CommandAPDU. This change will affect all existing CardServices. Here is an example of reusing an existing CommandAPDU object:apdu.setLength(0);
apdu.append(cla);
apdu.append(ins);
apdu.append(p1);
apdu.append(p2);
The new class ISOCommandAPDU in opencard.opt.terminal
provides the constructors formerly found in CommandAPDU, along
with the extended diagnostic output in toString. It is meant as
a help for debugging, but should not be used in production code.
For consistency of method names, pduLength and pduBytes
have been renamed to getLength and getBytes, respectively.
This will require minor changes in existing CardTerminal implementations.
CardService Instantiation
In OCF 1.0, CardService instantiation used the java.lang.reflect package. The dependency on the reflections package is a major drawback, since OCF should support embedded devices with small memory resources, too. To overcome this problem, a CardService for OCF 1.1 has to provide a default constructor without arguments.If the constructor with three arguments, as required for OCF 1.0, did nothing but invoke the base class constructor, just define an empty public default constructor. If the constructor performed initializations that depend on those arguments, the method CardService.initialize has to be overwritten. In this case, don't forget to invoke the base class implementation of that method.
For sake of method name consistency, chvDialog has been renamed to getCHVDialog. Also, the documentation of CardService and it's methods has been extended.
IO classes
The java.io specializations provided by OCF in the opencard.opt.iso.fs package have been reworked. The API offered some features that have never been implemented, or refer to non-ISO functionality that can not be expected of a file system based smartcard. Some of the changes are also related to the revised File Services. In particular, the following changes have been implemented:- Class CardFileOpenMode has been removed.
- The class was an anachronism related to concepts that have been dropped for OCF 1.0. Whether card access is blocking or not is specified at the time a CardService is created. When creating an instance of CardFile, it is already fixed and cannot be overridden. Removing this class resulted in changes to the constructors of CardFile.
- Class CardFileInfo has been replaced by an interface.
- The class CardFileInfo imposed a fixed structure on the implementation of a file service. For example, it required the service to cache whether a PIN has been entered for accessing a file. And, obviously, the class used by a service to represent file info had to be derived of CardFileInfo.
- Class CardFileType has been removed.
- The class CardFileType, which indicated whether a file is a directory or a data file with a particular structure, has been replaced by a set of query methods in CardFileInfo (see above). Instead of asking the file info for the file type and comparing the type to a predefined constant, the file info can be asked directly whether it is a directory, a cyclic file, and so on. This seems more natural in an object-oriented environment and reduces the code size of the framework.
- Class CardAccess has been removed.
- Class CardAccess was meant to represent access conditions to files on the smartcard. Unfortunately, not all kind of access conditions could be represented by that class or a specialization of it. For example, disjunctions of conditions, like "CHV or external authentication" could not be dealt with. Apart from that, the class was needed only at two places: the class CardFileInfo from which it has been removed (see above) and when creating files, which is not part of the ISO 7816-4 functionality (see below).
- Class CardFile has been revised.
- The class CardFile in OCF 1.0 was modelled closely after the class java.io.File. This resulted in some methods that are hard or impossible to map to smartcards, like list or readable. These have been removed, along with some attributes that are not really needed, like fileSeparator.
- The key handling has been revised and moved.
- The classes KeyStore and KeyBag defined a key handling mechanism required for satisfying access conditions that involve cryptography. This functionality is not specific to file system accesses, or even file system based smartcards. The key handling has therefore been revised and moved to the package opencard.opt.security. (Details)
This situation has been relaxed by replacing the class by an interface. The interface defines some methods to query standard information, for example whether it is a directory or a data file. The amount of data that can be queried has been reduced to what is needed for file access. For example, there is no method to query access conditions since it is up to the file service to deal with them.
Implementing a request of the CardService workgroup, the class CardAccess has therefore been removed. A file service implementation can represent access conditions as part of the file info in any way suitable for the particular smartcard. Applications should not have to deal with access conditions at all, since it is the responsibility of the card service to satisfy them.
The references to the removed classes mentioned above had to be removed. This implied changing all constructors to remove the reference to CardFileOpenMode. The create method has been changed to the new FileSystemCardService interface (see below). mkdir has been removed completely, since it would have been identical to the new create.
Some methods have been renamed for consistency. For example, path is now getPath, length is now length, and fileInfo became getFileInfo. Duplicate methods that accepted a string instead of a CardFilePath have been removed, to minimize the number of temporary objects that are created.
For convenience, CardFile implements the CardFileInfo (see above). All methods are mapped to invocations of the file info object returned by the underlying file service. The advantage is that methods like isDirectory can be invoked directly on the CardFile object instead of getting the info first.
File Services
The interface FileSystemCardService as defined in OCF 1.0 suffered from several drawbacks. First of all, it required support for functionality that is not defined in ISO 7816-4, like creating files. Second, it introduced dependencies on many of the classes defined in the opencard.opt.iso.fs package. Third, it defined key handling functionality that is not specific to the file system, but could also be required for signature generation or other operations supported by a smartcard. To overcome these drawbacks, several changes have been implemented.The key handling functionality has been moved from opencard.opt.iso.fs
to opencard.opt.security (see below).
The ISO functionality has been moved to a new, simpler interface named
FileAccessCardService. The name has been chosen since ISO specifies
only commands for accessing files and their contents, but not the creation,
deletion or comparable operations typically found in a file system. The
FileSystemCardService extends the file access interface by methods
to do exactly that. It is up to the developers of file services whether
one or both interfaces are implemented. Applications should use only the
file access interface to be independent of a particular smartcard.
To reduce the dependencies on other classes and interfaces in the iso.fs
package, the signatures of the methods in both service interfaces have
been changed. The dependencies are now restricted to the class CardFilePath
and the interface CardFileInfo. Dependencies on CardFileOpenMode,
CardFile, CardFileType, CardAccess, CardRecord
(and maybe some more) have been removed. Unfortunately, this requires changes
in existing implementations of the file system service. Applications will
need some minor changes, too.
Here are the highlights of the changes in the file service interfaces:
- The target files are specified by CardFilePath arguments rather than CardFile arguments.
- The mount methods have been removed. To obtain a CardFile object for the master file, just pass the file service to the constructor of that class. To refer to a file with an absolute path, the constructor gets the file service and the path.
- A method named getRoot has been introduced. It is meant to return the path to the master file of the smartcard. That way, it is possible to implement file services for cards with a master file id that is different from the ISO-specified 0x3f00. (Yes, there are such cards.)
- A method named readRecords has been introduced in the new FileAccessCardService. It is meant for reading cyclic files. Along with a magic number, it can also be used to read all records of a structured file. This is the only way to read a linear variable file completely without having to catch an exception at the end of the file.
- The create method in FileSystemCardService has a new interface. It expects a card-specific data block that describes the file to be created, including file type and access conditions. Even with the old interface, it was not really possible to create a file in a card-independent way, but now it is obvious.
- The API documentation of both file service interfaces has been greatly enhanced. It should now be precise enough to implement and use the interfaces conveniently.
The new interface is intended for scenarios in which a card application has to be loaded from a host to a smartcard. We assumed that the host is able to prepare the card-specific data block and sends it to the OCF program that invokes create. Besides, developers still have a chance to create files on particular cards for testing purposes.
Signature Services
The interface SignatureCardService as defined in OCF 1.1 suffered from several drawbacks. First, it merged the functionality of generating and verifying signatures with that of importing keys to the smartcard. Second, the support was restricted to the RSA algorithm. DSA, or other algorithms that may become important in the future could not be integrated. Third, there was no interface for generating key pairs on the smartcard itself, which is supported by some cards. Fourth, using the smartcards for signatures may require satisfying access conditions similar to those for file access (see File Services above), but there was no way to pass authentication keys to the service. Last but not least, the SignatureCardService in OCF 1.0 used CardFilePath to refer to keys. The interface could therefore only be used for file system based smartcards, but not for JavaCards.To overcome these problems, the interface SignatureCardService
has been split, the method signatures have been changed to support various
public key algorithms, and a new interface for key generation on the card
has been defined. All interfaces extend SecureService (see Key
Handling below) so authentication keys can be provided. Of course,
the documentation of the methods has been enhanced.
Here are the three interfaces in opencard.opt.signature and
a short description of the functionality they define:
- SignatureCardService
- Provides methods to sign and to verify signatures on data or hashs on data. References to the keys on the smartcard are generic and can be specialized to paths or cardlets. The algorithm for signature generation or verification can be specified by strings. The algorithm names are those defined by the Java Cryptography Architecture (JCA). Optionally, the padding algorithm can be specified in the same way.
- KeyImportCardService
- This extension of the SignatureCardService defines methods to import private or public keys to a smartcard. Import can be done with plain keys, or with keys that have a signature attached to them which will be checked by the card. Generic references are used to specify the place to put the key.
- KeyGenerationCardService
- This extension of the SignatureCardService defines a method to generate a key pair, that is a private key and matching public key, on the card. A second method is defined to read the generated public key from the card. The private key will never leave the card, which ensures a high level of privacy.
The OCF 1.0 methods to generate and verify signatures are still defined in the interface, but deprecated. These methods introduce a dependency on the opencard.opt.iso.fs package. They are likely to be removed in future versions of OCF, for example for embedded devices.
Generic key representations are used to pass the key data. A particular implementation of this CardService interface will convert the generic representation to a card specific one. In OCF 1.0, the key had to be passed in a card specific representation.
Key Handling
In OCF 1.0, the FileSystemCardService interface was the only one that defined support for secret keys. Such keys are used to satisfy access conditions that involve cryptography. The concept for key handling was that an application provides the keys, while the service contains the cryptographic code to satisfy the access conditions. For OCF 1.1, several changes regarding key handling have been implemented:- The key handling has been moved from opencard.opt.iso.fs to opencard.opt.security. The interface SecureService in that package can be extended by any CardService interface. Standard interfaces that do so are FileAccessCardService (see File Services) and SignatureCardService (see Signature Services). The interface of SecureService uses generic identifiers for security domains, instead of CardFile as in OCF 1.0. That way, the interface is appropriate for JavaCards, too.
- Keys have been replaced by credentials, in the concept as well as in class names. Unlike a key, a credential may include cryptographic code as well as the key material. Instead of using a key with it's own cryptographic code, a CardService may use methods defined in a credential's interface to encrypt, decrypt, compute a MAC, or generate a cryptographically strong random number. This is a prerequisite for supporting a Secure Access Module (SAM) that performs such operations without revealing the keys stored in it.
This page was created by Frank Seliger, Roland Weber and Lothar Merk.
