WIMApplicationpublic class WIMApplication extends Object This class provides interface to WIM card application. |
Fields Summary |
---|
static final int | SKIPOperation result constant (skip this SE and try next). | static final int | SUCCESSOperation result constant. | static final int | CANCELOperation result constant. | static final int | ERROROperation result constant. | private com.sun.midp.security.SecurityToken | securityTokenThis class has a different security domain than the MIDlet
suite | private static final byte | INS_VERIFYINS byte for APDU command. | private static final byte | INS_MSEINS byte for APDU command. | private static final byte | INS_PSOINS byte for APDU command. | static final byte | INS_NEWINS byte for command APDU. | private static final int | PIN_BLOCKEDPIN status constant. | private static final int | PIN_DISABLEDPIN status constant. | private static final int | PIN_REQUIREDPIN status constant. | private static final int | PIN_CANCELLEDPIN status constant. | private static final short | ODFPathODF path. | private static final short | TokenInfoPathEF(TokenInfo) path. | private static final short | UnusedSpaceEF(UnusedSpace) path. | private static final int | PRIVATE_KEYS_TAGODF entry tag. | private static final int | PUBLIC_KEYS1_TAGODF entry tag. | private static final int | PUBLIC_KEYS2_TAGODF entry tag. | private static final int | USEFUL_CERTIFICATES_TAGODF entry tag. | private static final int | TRUSTED_CERTIFICATES_TAGODF entry tag. | private static final int | USER_CERTIFICATES_TAGODF entry tag. | private static final int | PINS_TAGODF entry tag. | private static final byte[] | selectAPDUsAPDUs that must be used for WIM application selection. | private static final byte[] | WIM_GENERIC_RSA_OIDBinary representation of WIM_GENERIC_RSA SE OID, 2.23.43.1.1.2 | private static final byte[] | WAP_WSG_WIMPATHBinary representation of WAP_WSG_WIMPATH OID, 2.23.43.1.3 | private static final byte[] | DigestInfoHeaderRSA digest header. | private Connection | apduConnection object. | private WimFileSystem | filesFile system object. | private int | WIM_GENERIC_RSA_IDIdentifier of WIM_GENERIC_RSA SE | private int | RSA_ALGORITHM_IDIdentifier of RSA algorithm in EF(TokenInfo) and PrKDFs. | private boolean | readOnlyIf true this WIM application doesn't allow to modify data. | private String | serialNumberSerial number of this WIM card. | private Vector | ODFThis vector contains parsed objects from DF(ODF). | private PrivateKey[] | PrKeysPrivate keys. | private PublicKey[] | PuKeysPublic keys. | private com.sun.satsa.acl.PINAttributes[] | PINsPINs. | private Certificate[] | CertificatesCertificates. | private Vector | certificateIDsVector contains identifiers of existing certificates. | private Vector | loaderObjectsThis vector contains objects loaded from directory file. | private Vector | loaderLocationsThis vector contains locations of loaded objects. | private Vector | loaderFreeBlocksThis vector contains locations of free space in directory
files. | private short[] | UnusedSpacePathFull path to EF(UnusedSpace) file. | private Vector | updateLocationsVector contains locations of blocks that must be updated. | private Vector | updateDataVector contains values that must be written. | private boolean[] | updatePINFlags that indicate which PINs must be verified before the
update. |
Constructors Summary |
---|
private WIMApplication(com.sun.midp.io.j2me.apdu.Handle h)Constructs a new WIMApplication object.
this.apdu = new Connection(h);
files = new WimFileSystem(apdu);
securityToken = h.token;
|
Methods Summary |
---|
public int | addCredential(java.lang.String label, TLV top, java.util.Vector keyIDs)Adds a user certificate or certificate URI to a certificate store.
See UserCredentialManager.addCredential for details. Calling
method must remove leading and trailing spaces in label.
// load existing certificates
try {
loadPrivateKeys();
loadCertificates(true, true);
} catch (IOException e) {
return SKIP;
}
// put certificates into array
Vector u = new Vector();
while (top != null) {
u.addElement(top);
top = top.next;
}
TLV path[] = new TLV[u.size()];
u.copyInto(path);
// verify certificates encoding and calculate identifier
// the purpose of the check is to ensure that new certificates
// will not cause runtime exceptions, not to verify X.509
// compliance
byte[][] IDs = new byte[path.length][];
try {
TLV Issuer = null;
for (int i = 0; i < path.length; i++) {
TLV t = path[i].child.child.skipOptional(0xa0).next.next;
RFC2253Name.compare(t, t); // issuer
if (Issuer != null && ! RFC2253Name.compare(Issuer, t)) {
throw new IllegalArgumentException();
}
t = t.next; // validity
t.child.getTime(); // notBefore
t.child.next.getTime(); // notAfter
t = t.next; // subject
RFC2253Name.compare(t, t);
Issuer = t;
IDs[i] = getKeyHash(path[i]); // subjectPublicKeyInfo
}
} catch (IOException e) {
throw new IllegalArgumentException("Invalid pkiPath");
} catch (NullPointerException npe) {
throw new IllegalArgumentException("Invalid pkiPath");
}
// check if this WIM contains corresponding private key
if (getPrivateKey(IDs[path.length - 1]) == null) {
return SKIP;
}
// check that the label is unique for this card
if (getCertificate(label) != null) {
throw new IllegalArgumentException(label);
}
// eliminate certificates that already present on the card
for (int i = 0; i < path.length; i++) {
TLV t = path[i].child.child.skipOptional(0xa0);
if (getCertificate(t.next.next, t) != null) {
path[i] = null;
}
}
if (path[path.length - 1] == null) {
throw new IllegalArgumentException("credential exists");
}
// if the 1st certificate is self-signed we don't need to save it
if (path.length > 1 && path[0] != null) {
TLV t = path[0].child.child.skipOptional(0xa0).next.next;
if (RFC2253Name.compare(t, t.next.next)) {
path[0] = null;
}
}
// find place for every certificate and generate CDF records
startUpdate();
Location[] locations;
try {
locations = putObjects(path);
} catch (IOException e) {
return ERROR;
}
if (locations == null) { // if no enough space
return ERROR;
}
Vector headers = new Vector();
int labelNum = 0;
for (int i = 0; i < path.length; i++) {
if (path[i] == null) {
continue;
}
// generate header for certificate
// create unique label if necessary
String t_label = label;
if (i < path.length - 1) {
for (int k = 0; k < 100000; k++) {
t_label = "certificate # " + labelNum++;
if (! label.equals(t_label) &&
getCertificate(t_label) == null) {
break;
}
}
}
// find identifier of the previous certificate
byte[] prevID;
if (i == 0) {
TLV t = path[i].child.child.skipOptional(0xa0).next.next;
Vector v = getCertsBySubject(t);
if (v.size() == 0) {
prevID = new byte[20];
} else {
prevID = ((Certificate) v.elementAt(0)).id;
}
} else {
prevID = IDs[i - 1];
}
TLV commonAttrs = TLV.createSequence();
commonAttrs.
setChild(createLabel(t_label)).
setNext(new TLV(TLV.BITSTRING_TYPE, new byte[2]));
TLV commonCertAttrs = TLV.createSequence();
commonCertAttrs.
setChild(TLV.createOctetString(IDs[i])).
setNext(TLV.createOctetString(prevID));
Location l = locations[i];
TLV x509Attrs = new TLV(0xa1);
x509Attrs.setChild(TLV.createSequence()).
setChild(createPath(l.path, l.offset, l.length));
TLV cdf = TLV.createSequence();
cdf.setChild(commonAttrs).
setNext(commonCertAttrs).
setNext(x509Attrs);
headers.addElement(cdf);
}
// find free space for headers in CDFs
if (! putHeaders(headers)) {
return ERROR;
}
// check PINs
for (int i = 0; i < updatePIN.length; i++) {
if (updatePIN[i]) {
int pinStatus = checkPIN(PINs[i]);
if (pinStatus == PIN_CANCELLED) {
return CANCEL;
}
if (pinStatus == PIN_BLOCKED) {
throw new SecurityException("PIN blocked");
}
if (pinStatus != PIN_DISABLED) {
return ERROR;
}
}
}
// update
try {
doUpdate();
} catch (IOException e) {
return ERROR;
}
// remove key identifier from the list of expected certificates
for (int i = 0; i < keyIDs.size(); i++) {
if (Utils.byteMatch(IDs[path.length - 1],
(byte[]) keyIDs.elementAt(i))) {
keyIDs.removeElementAt(i);
break;
}
}
// typeInfo("AddCredential");
return SUCCESS;
| private int | checkPIN(com.sun.satsa.acl.PINAttributes pin)Verifies the PIN if necessary.
while (true) {
int status = getPINStatus(pin);
if (status == PIN_DISABLED) {
return PIN_DISABLED;
}
if (status == PIN_BLOCKED) {
try {
MessageDialog
.showMessage(securityToken,
Resource.getString(ResourceConstants
.ERROR),
Resource
.getString(ResourceConstants
.JSR177_WIM_PIN_BLOCKED) + ":\n" +
pin.label,
false);
} catch (InterruptedException e) {}
return PIN_BLOCKED;
}
// verification is required
PINEntryDialog dialog;
try {
dialog = new PINEntryDialog(securityToken,
ACLPermissions.CMD_VERIFY,
pin, null);
} catch (InterruptedException e) {
return PIN_CANCELLED;
}
dialog.waitForAnswer();
Object[] pins = dialog.getPINs();
if (pins == null) {
return PIN_CANCELLED;
}
boolean ok = true;
try {
byte[] tmp = (byte[]) pins[0];
apdu.resetCommand().
putBytes(tmp, 0, tmp.length).
sendCommand(INS_VERIFY, pin.pinReference, 127, false);
} catch (IOException e) {
ok = false;
}
if (ok & (apdu.lastSW == 0x9000)) {
return PIN_DISABLED;
}
try {
MessageDialog
.showMessage(securityToken,
Resource
.getString(ResourceConstants
.ERROR),
Resource
.getString(ResourceConstants
.JSR177_WIM_PIN_NOT_VERIFIED),
false);
} catch (InterruptedException e) {}
}
| private static boolean | comparePaths(short[] path1, short[] path2)Compares two paths.
if (path1.length != path2.length) {
return false;
}
for (int i = 0; i < path1.length; i++) {
if (path1[i] != path2[i]) {
return false;
}
}
return true;
| private static TLV | createLabel(java.lang.String label)Pads the string to 32 bytes as recommended in WIM and returns TLV
value that can be used as label.
int len = Utils.stringToBytes(label).length;
while (len < 32) {
label = label + " ";
len++;
}
return TLV.createUTF8String(label);
| private TLV | createPath(short[] path, int offset, int length)Creates PKCS#15 path.
TLV t = TLV.createSequence();
t.setChild(TLV.createOctetString(Utils.shortsToBytes(path))).
setNext(TLV.createInteger(Utils.shortToBytes(offset))).
setNext(TLV.createInteger(Utils.shortToBytes(length)).
setTag(0x80));
return t;
| private void | deleteBlock(Location l)Mark record of EF(UnusedSpace) as unused.
update(UnusedSpacePath, l.offset, getEmptySpaceHeader(l.length));
| private static void | doParseDF(byte[] data, short[] path, java.util.Vector objects, java.util.Vector locations, java.util.Vector freeBlocks)Parses EF(DF).
int start = 0;
int current = 0;
while (current < data.length) {
// free space - skip
if (data[current] == (byte) 0xff) {
current++;
continue;
}
// TLV object
TLV t = new TLV(data, current);
// empty one - skip
if (t.type == 0) {
current = t.valueOffset + t.length;
continue;
}
// real object
if (objects != null) {
objects.addElement(t);
}
if (locations != null) {
locations.addElement(new Location(path, current,
t.valueOffset + t.length - current));
}
if (freeBlocks != null && start < current) {
freeBlocks.addElement(
new Location(path, start, current - start));
}
current = t.valueOffset + t.length;
start = current;
}
if (start < current && freeBlocks != null) {
freeBlocks.addElement(
new Location(path, start, current - start));
}
| private void | doRemove(java.util.Vector chain, int count)Register all necessary file updates for certificate removal.
// Load and parse UnusedSpace.
files.select(UnusedSpacePath);
Vector v_free = new Vector(); // records in UnusedSpace
Vector v_location = new Vector(); // their offsets
Vector v_hole = new Vector(); // empty space in the file
doParseDF(files.readFile(), UnusedSpacePath,
v_free, v_location, v_hole);
TLV[] free = new TLV[v_free.size()];
v_free.copyInto(free);
Location[] block = new Location[free.length];
for (int i = 0; i < free.length; i++) {
block[i] = files.pathToLocation(free[i].child);
}
for (int i = 0; i < count; i++) {
Certificate cert = (Certificate) chain.elementAt(i);
// remove the certificate header from CDF
update(cert.header.path, cert.header.offset,
getEmptySpaceHeader(cert.header.length));
// Now area in data file must be marked as unused.
// try to append/prepend the new block to existing blocks
Location hole = cert.body;
int head = -1;
int tail = -1;
int empty = -1;
for (int k = 0; k < block.length; k++) {
if (block[k] == null ||
! comparePaths(hole.path, block[k].path)) {
continue;
}
if (block[k].length == 0) {
empty = k;
continue;
}
if (doesFollow(block[k], hole)) {
head = k;
continue;
}
if (doesFollow(hole, block[k])) {
tail = k;
}
}
if (head != -1 && tail != -1) {
block[head].length = block[head].length + hole.length +
block[tail].length;
setBlockLength(free[head], block[head].length);
Location newHole = (Location) v_location.elementAt(tail);
deleteBlock(newHole);
v_hole.addElement(newHole);
block[tail] = null;
continue;
}
if (head != -1) {
block[head].length += hole.length;
setBlockLength(free[head], block[head].length);
continue;
}
if (tail != -1) {
block[tail].offset -= hole.length;
block[tail].length += hole.length;
setBlockOffset(free[tail], block[tail].offset);
setBlockLength(free[tail], block[tail].length);
continue;
}
if (empty != -1) {
block[empty].offset = hole.offset;
block[empty].length = hole.length;
setBlockOffset(free[empty], block[empty].offset);
setBlockLength(free[empty], block[empty].length);
continue;
}
// this is a new block, have to allocate new entry
// generate new record with PIN-G authId
TLV n = TLV.createSequence();
TLV t = n.setChild(createPath(hole.path, hole.offset,
hole.length));
t.setNext(TLV.createOctetString(new byte[] {(byte) PINs[0].id}));
byte[] data = n.getDERData();
// find space for new entry
Location l = null;
for (int k = 0; k < v_hole.size(); k++) {
Location loc = (Location) v_hole.elementAt(k);
if (loc.length >= data.length) {
l = loc;
break;
}
}
if (l == null) {
throw new IOException(
"Can't allocate new entry in EF(UnusedSpace)");
}
// update data
update(UnusedSpacePath, l.offset, data);
l.offset += data.length;
l.length -= data.length;
if (l.length != 0) {
update(UnusedSpacePath, l.offset,
getEmptySpaceHeader(l.length));
}
}
| private void | doUpdate()Performs all the registered updates.
for (int i = 0; i < updateLocations.size(); i++) {
Location l = (Location) updateLocations.elementAt(i);
files.select(l.path);
byte[] d = (byte[]) updateData.elementAt(i);
files.writeData(d, 0, d.length, l.offset);
}
updateLocations = null;
updateData = null;
| private static boolean | doesFollow(Location a1, Location a2)Verifies if the second block starts right after the fist.
return (a1.offset + a1.length == a2.offset);
| public void | done()Safely closes the connection.
if (apdu != null) {
apdu.done();
}
apdu = null;
| public byte[] | generateCSR(java.lang.String nameInfo, int keyLen, int keyUsage, boolean forceKeyGen, java.util.Vector keyIDs)Generates CSR. See UserCredentialManager.generateCSR for details.
The calling method must load a vector that contains IDs of keys
for which CSRs were generated earlier and save it after successful
CSR generation.
// check the name
if (nameInfo == null) {
nameInfo = "CN=" + serialNumber;
}
TLV name;
try {
name = new TLV(RFC2253Name.toDER(nameInfo), 0);
} catch (TLVException e) {
throw new IllegalArgumentException("Invalid name");
}
try {
if (MessageDialog.showMessage(securityToken,
Resource.getString(ResourceConstants.AMS_CONFIRMATION),
Resource.getString(ResourceConstants.
JSR177_CERTIFICATE_GENERATED) +
"\n\n" +
// "Name: "
Resource.getString(ResourceConstants.
JSR177_CERTIFICATE_SUBJECT) + ": " +
nameInfo +
"\n\n" +
// "Key usage: "
Resource.getString(ResourceConstants.
JSR177_CERTIFICATE_KEYUSAGE) + ": " +
((keyUsage ==
UserCredentialManager.KEY_USAGE_AUTHENTICATION) ?
// "authentication"
Resource.getString(ResourceConstants.
JSR177_CERTIFICATE_KEYUSAGE_AUTH) :
// "non-repudiation"
Resource.getString(ResourceConstants.
JSR177_CERTIFICATE_KEYUSAGE_NR)) +
"\n" +
// "Algorithm: "
Resource.getString(ResourceConstants.
JSR177_CERTIFICATE_ALGORITHM) + ": " +
"RSA" +
"\n" +
// "Key length: "
Resource.getString(ResourceConstants.
JSR177_CERTIFICATE_KEYLENGTH) + ": " +
keyLen,
true) == Dialog.CANCELLED) {
return null;
}
} catch (InterruptedException e) {
return null;
}
int keyId = -1;
if (forceKeyGen) {
try {
keyId = generateKey(keyLen, keyUsage);
} catch (IOException ioe) { // ignored
} catch (InterruptedException ie) { // ignored
}
if (keyId == -1) {
throw new UserCredentialManagerException(
UserCredentialManagerException.SE_NO_KEYGEN);
}
if (keyId == -2) {
throw new UserCredentialManagerException(
UserCredentialManagerException.SE_NO_KEYS);
}
}
// load info about keys
try {
if (keyId != -1) {
loadPINs();
}
loadCertificates(false, true);
loadPrivateKeys();
loadPublicKeys();
} catch (IOException e) {
throw new UserCredentialManagerException(
UserCredentialManagerException.SE_NO_KEYS);
}
// find the 'best' key
PrivateKey key = null;
int keyType = 3; // 0 - no certificate or CSR
// 1 - CSR
// 2 - certificate
// 3 - empty
TLV keyValue = null;
for (int i = 0; i < PrKeys.length; i++) {
if (keyId != -1) {
if (keyId == PrKeys[i].keyReference) {
key = PrKeys[i];
keyValue = getPublicKey(PrKeys[i].id);
break;
}
continue;
}
// check key size
if (PrKeys[i].modulusLength != keyLen) {
continue;
}
// check key usage
if (! (keyUsage ==
UserCredentialManager.KEY_USAGE_AUTHENTICATION ?
PrKeys[i].authentication :
PrKeys[i].nonRepudiation)) {
continue;
}
// check if certificate or CSR for this key exists
int type = 0;
if (getIDIndex(keyIDs, PrKeys[i].id) != -1) {
type = 1;
}
if (getIDIndex(certificateIDs, PrKeys[i].id) != -1) {
type = 2;
}
// is this key is better than the previous?
if (type >= keyType) {
continue;
}
// if PIN doesn't exist or blocked, find another key
PINAttributes pin = getPIN(PrKeys[i].authId);
if (pin == null || getPINStatus(pin) == PIN_BLOCKED) {
continue;
}
// if the public key can't be retrieved, find another key
TLV t = getPublicKey(PrKeys[i].id);
if (t == null) {
continue;
}
// the best key so far
key = PrKeys[i];
keyValue = t;
keyType = type;
}
if (key == null) {
throw new UserCredentialManagerException(
UserCredentialManagerException.SE_NO_KEYS);
}
// the key is found and loaded
// check PIN for signature operation
int pinStatus = checkPIN(getPIN(key.authId));
if (pinStatus == PIN_CANCELLED) {
return null;
}
if (pinStatus == PIN_BLOCKED) {
throw new SecurityException("PIN blocked");
}
if (pinStatus != PIN_DISABLED) {
// IMPL_NOTE: need warning message?
throw new CMSMessageSignatureServiceException(
CMSMessageSignatureServiceException.SE_CRYPTO_FAILURE);
}
// PIN is verified, create the CSR
TLV CRInfo = TLV.createSequence();
CRInfo.setChild(TLV.createInteger(0)).
setNext(name).
setNext(keyValue).
setNext(new TLV(TLV.SET_TYPE).setTag(0xa0)).
setChild(TLV.createSequence()).
setChild(TLV.createOID("1.2.840.113549.1.9.14")).
setNext(new TLV(TLV.SET_TYPE)).
setChild(TLV.createSequence()).
setChild(TLV.createSequence()).
setChild(TLV.createOID("2.5.29.15")).
setNext(new TLV(TLV.BOOLEAN_TYPE, new byte[] {(byte) 255})).
setNext(new TLV(TLV.OCTETSTR_TYPE,
keyUsage == UserCredentialManager.KEY_USAGE_AUTHENTICATION ?
new byte[] {3, 2, 7, (byte) 0x80} :
new byte[] {3, 2, 6, 0x40}));
byte[] sign;
try {
sign = signData(key, CRInfo.getDERData());
} catch (IOException e) {
throw new CMSMessageSignatureServiceException(
CMSMessageSignatureServiceException.SE_CRYPTO_FAILURE);
}
TLV alg = CRInfo.child.next.next.child.copy();
TLV OID = TLV.createOID("1.2.840.113549.1.1.5");
TLV params = alg.child.next;
alg = TLV.createSequence();
alg.setChild(OID).setNext(params);
TLV request = TLV.createSequence();
request.setChild(CRInfo).
setNext(alg).
setNext(new TLV(TLV.BITSTRING_TYPE, sign));
// add to the vector of IDs of keys for which CSRs are generated
keyIDs.addElement(key.id);
return request.getDERData();
| int | generateKey(int keyLen, int keyUsage)Generates new key.
boolean nonRepudiation = (keyUsage ==
UserCredentialManager.KEY_USAGE_NON_REPUDIATION);
byte[] tmp = apdu.resetCommand().
putByte(nonRepudiation ? 1 : 0).
putShort(keyLen).
sendCommand(INS_NEW, 0x0100, 240, false);
if (apdu.lastSW == 0x9001) {
return -2;
}
if (tmp.length != 6 ||
Utils.getShort(tmp, 0) != 0x1234 ||
Utils.getShort(tmp, 2) != 0x4321) {
return -1;
}
apdu.resetCommand().
putByte(nonRepudiation ? 1 : 0).
putShort(keyLen);
if (nonRepudiation) {
// must create new PIN
String[] pinInfo = MessageDialog.enterNewPIN(securityToken);
if (pinInfo == null) {
return -1;
}
tmp = pinInfo[1].getBytes();
int len = tmp.length;
apdu.putBytes(tmp, 0, len);
while (len++ < 8) {
apdu.putByte(0xff);
}
tmp = Utils.stringToBytes(pinInfo[0]);
len = tmp.length < 32 ? tmp.length : 32;
apdu.putBytes(tmp, 0, len);
while (len++ < 32) {
apdu.putByte(0x20);
}
}
tmp = apdu.sendCommand(INS_NEW, 0x0000, 240, false);
return apdu.lastSW == 0x9000 ? tmp[0] & 0xff : -2;
| public byte[] | generateSignature(boolean nonRepudiation, byte[] data, int options, TLV[] caNames)Generates a signature.
// load existing certificates
try {
loadPrivateKeys();
loadCertificates(true, true);
} catch (IOException e) {
throw new CMSMessageSignatureServiceException(
CMSMessageSignatureServiceException.SE_FAILURE);
}
// find certificate chains
Vector chains = getChains(nonRepudiation, caNames);
if (chains.size() == 0) {
throw new CMSMessageSignatureServiceException(
CMSMessageSignatureServiceException.CRYPTO_NO_CERTIFICATE);
}
// select certificate
Vector chain = selectChain(chains);
if (chain == null) {
return null;
}
Certificate cert = (Certificate) chain.elementAt(0);
PrivateKey key = getPrivateKey(cert.id);
PINAttributes pin = getPIN(key.authId);
int pinStatus = checkPIN(pin);
if (pinStatus == PIN_BLOCKED) {
throw new SecurityException();
}
if (pinStatus == PIN_CANCELLED) {
return null;
}
TLV signedAttrs = new TLV(TLV.SET_TYPE);
TLV t = signedAttrs.setChild(TLV.createSequence());
t.setChild(TLV.createOID("1.2.840.113549.1.9.3")). // ContentType
setNext(new TLV(TLV.SET_TYPE)).
setChild(TLV.createOID("1.2.840.113549.1.7.1")); // data
t.next = TLV.createSequence();
t = t.next;
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
t.setChild(TLV.createOID("1.2.840.113549.1.9.5")). // signingTime
setNext(new TLV(TLV.SET_TYPE)).
setChild(TLV.createUTCTime(calendar));
t.next = TLV.createSequence();
t = t.next;
t.setChild(TLV.createOID("1.2.840.113549.1.9.4")). // messageDigest
setNext(new TLV(TLV.SET_TYPE)).
setChild(TLV.createOctetString(Utils.getHash(data, 0, data.length)));
// generate signature
byte[] signature;
try {
signature = signData(key, signedAttrs.getDERData());
} catch (IOException e) {
throw new CMSMessageSignatureServiceException(
CMSMessageSignatureServiceException.CRYPTO_FAILURE);
}
// format the signature
/*
* ContentInfo ::= SEQUENCE {
* contentType ContentType,
* content [0] EXPLICIT ANY DEFINED BY contentType }
*
* ContentType ::= OBJECT IDENTIFIER
*
* id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
* us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 }
*/
TLV ContentInfo = TLV.createSequence();
t = ContentInfo.
setChild(TLV.createOID("1.2.840.113549.1.7.2")).
setNext(new TLV(0xa0)).
setChild(TLV.createSequence());
/*
* t - SignedData
* SignedData ::= SEQUENCE {
* version CMSVersion,
* digestAlgorithms DigestAlgorithmIdentifiers,
* encapContentInfo EncapsulatedContentInfo,
* certificates [0] IMPLICIT CertificateSet OPTIONAL,
* - crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
* signerInfos SignerInfos }
*
* DigestAlgorithmIdentifiers ::= SET OF
* DigestAlgorithmIdentifier
*/
t = t.
setChild(TLV.createInteger(1)). // version
setNext(new TLV(TLV.SET_TYPE)); // digestAlgorithms
TLV SHAAlgId = TLV.createSequence();
SHAAlgId.setChild(TLV.createOID("1.3.14.3.2.26")); // SHA-1
t.setChild(SHAAlgId.copy());
/*
* EncapsulatedContentInfo ::= SEQUENCE {
* eContentType ContentType,
* eContent [0] EXPLICIT OCTET STRING OPTIONAL }
*
* ContentType ::= OBJECT IDENTIFIER
*
* id-data OBJECT IDENTIFIER ::= { iso(1) member-body(2)
* us(840) rsadsi(113549) pkcs(1) pkcs7(7) 1 }
*/
t = t.setNext(TLV.createSequence());
TLV m = t.setChild(TLV.createOID("1.2.840.113549.1.7.1"));
if ((options &
CMSMessageSignatureService.SIG_INCLUDE_CONTENT) != 0) {
m.setNext(new TLV(0xa0)).
setChild(TLV.createOctetString(data));
}
/*
* certificates [0] IMPLICIT CertificateSet OPTIONAL,
*
* CertificateSet ::= SET OF CertificateChoices
*
* CertificateChoices ::= CHOICE {
* certificate Certificate, -- See X.509
* extendedCertificate [0] IMPLICIT ExtendedCertificate,
* -- Obsolete
* attrCert [1] IMPLICIT AttributeCertificate }
*
*/
if ((options &
CMSMessageSignatureService.SIG_INCLUDE_CERTIFICATE) != 0) {
t = t.setNext(new TLV(0xa0));
TLV n = t.setChild(cert.cert);
for (int i = 1; i < chain.size(); i++) {
n = n.setNext(((Certificate) chain.elementAt(i)).cert);
}
}
/*
* signerInfos SignerInfos }
* SignerInfos ::= SET OF SignerInfo
*
* SignerInfo ::= SEQUENCE {
* version CMSVersion,
* sid SignerIdentifier,
* digestAlgorithm DigestAlgorithmIdentifier,
* signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
* signatureAlgorithm SignatureAlgorithmIdentifier,
* signature SignatureValue,
* - unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }
*
* SignerIdentifier ::= CHOICE {
* issuerAndSerialNumber IssuerAndSerialNumber,
* - subjectKeyIdentifier [0] SubjectKeyIdentifier }
*
* IssuerAndSerialNumber ::= SEQUENCE {
* issuer Name,
* serialNumber CertificateSerialNumber }
*
*/
t = t.setNext(new TLV(TLV.SET_TYPE)).
setChild(TLV.createSequence()).
setChild(TLV.createInteger(1)).
setNext(cert.getIssuerAndSerialNumber()).
setNext(SHAAlgId). // SHA-1
setNext(signedAttrs).setTag(0xa0).
setNext(cert.getKeyAlgorithmID()).
setNext(new TLV(TLV.OCTETSTR_TYPE, signature, 1));
return ContentInfo.getDERData();
| private Certificate | getCertificate(java.lang.String label)Returns certificate for given label.
for (int i = 0; i < Certificates.length; i++) {
if (Certificates[i].label.equals(label)) {
return Certificates[i];
}
}
return null;
| private Certificate | getCertificate(TLV issuer, TLV serialNumber)Returns certificate for given issuer and serial number.
for (int i = 0; i < Certificates.length; i++) {
TLV t = Certificates[i].cert.child.child.skipOptional(0xa0);
if (t.match(serialNumber) &&
t.next.next.match(issuer)) {
return Certificates[i];
}
}
return null;
| private java.util.Vector | getCertsBySubject(TLV subject)Returns certificates for given subject.
Vector v = new Vector();
for (int i = 0; i < Certificates.length; i++) {
if (RFC2253Name.compare(subject,
Certificates[i].getSubject())) {
v.addElement(Certificates[i]);
}
}
return v;
| private java.util.Vector | getChain(Certificate cert, TLV[] caNames, boolean checkValidity)Builds certificate chain for given certificate.
Vector chain = new Vector();
while (true) {
if (checkValidity && cert.isExpired()) {
// the certificate is expired, can't build the chain
return null;
}
chain.addElement(cert);
TLV issuer = cert.getIssuer();
// if this is the certificate issued by one of the CAs in
// the list then the chain is complete
if (caNames != null) {
// check if we need any additional certificates
for (int i = 0; i < caNames.length; i++) {
if (RFC2253Name.compare(issuer, caNames[i])) {
return chain;
}
}
}
// search for the issuer certificate
boolean found = false;
for (int i = 0; i < Certificates.length; i++) {
Certificate next = Certificates[i];
found = cert.isIssuedBy(next) &&
! chain.contains(next);
if (found) {
cert = next;
break;
}
}
if (! found) {
// issuer certificate was not found
// if caNames is null, the chain is good enough,
// otherwise the chain is not found
return caNames == null ? chain : null;
}
}
| private java.util.Vector | getChains(boolean nonRepudiation, TLV[] caNames)Finds certificate chains for specified operation.
// find the chains
Vector chains = new Vector();
for (int i = 0; i < Certificates.length; i++) {
PrivateKey key = getPrivateKey(Certificates[i].id);
if ((key != null) && (nonRepudiation ? key.nonRepudiation :
key.authentication)) {
Vector chain = getChain(Certificates[i], caNames, true);
if (chain != null) {
chains.addElement(chain);
}
}
}
return chains;
| private static byte[] | getEmptySpaceHeader(int length)Creates block header that can be used to mark empty space in
directory file.
if (length == 1) {
return new byte[] {(byte) 0xff};
}
if (length < 130) {
return new byte[] {0, (byte) (length - 2)};
}
if (length < 259) {
return new byte[] {0, (byte) 0x81, (byte) (length - 3)};
}
length -= 4;
return new byte[] {0, (byte) 0x82, (byte) (length >> 8),
(byte) length};
| private int | getIDIndex(java.util.Vector IDs, byte[] id)Returns index of given identifier in the vector or -1 if not
found.
for (int j = 0; j < IDs.size(); j++) {
if (Utils.byteMatch((byte[]) IDs.elementAt(j), id)) {
return j;
}
}
return -1;
| public static com.sun.satsa.pki.WIMApplication | getInstance(com.sun.midp.security.SecurityToken token, int slotNum, java.lang.String securityElementID, boolean readOnly)Creates connection with WIM application (WIM spec, 11.3.3) on
card in specified slot. Doesn't throw exceptions.
for (int i = 0; i < selectAPDUs.length; i++) {
Handle h;
APDUManager.initACL(slotNum, token);
try {
h = APDUManager.selectApplication(
selectAPDUs[i], (byte) slotNum, token);
} catch (IOException e) {
continue;
}
WIMApplication w = new WIMApplication(h);
if (w.init(securityElementID) &&
(readOnly || (! w.readOnly))) {
return w;
}
w.done();
}
return null;
| private static byte[] | getKeyHash(TLV cert)Calculates public key hash for given X.509 certificate.
TLV t = cert.child.child.skipOptional(0xa0).
next.next.next.next.next.child;
// t is at subjectPublicKeyInfo.algorithm field
byte[] data;
int offset;
int length;
TLV m = t.child;
t = t.next;
if (m.match(TLV.createOID("1.2.840.113549.1.1.1"))) {
// RSA
data = (new TLV(t.data, t.valueOffset + 1).child).getValue();
offset = 0;
length = data.length;
} else
if (m.match(TLV.createOID("1.2.840.10045.2.1"))) {
// ECDSA
data = t.data;
offset = t.valueOffset + 2;
if (t.data[t.valueOffset + 1] == 4) {
// uncompressed form
length = (t.length - 2) / 2;
} else {
// compressed form
length = (t.length - 2);
}
} else {
// PKCS#15 doesn't say anything about this case
// just calculate the hash of subjectPublicKey data
data = t.data;
offset = t.valueOffset + 1;
length = t.length - 1;
}
return Utils.getHash(data, offset, length);
| private com.sun.satsa.acl.PINAttributes | getPIN(int authId)Returns PIN attributes for given authId.
for (int i = 0; i < PINs.length; i++) {
if (PINs[i].id == authId) {
return PINs[i];
}
}
return null;
| private int | getPINStatus(com.sun.satsa.acl.PINAttributes pin)Verifies PIN status.
try {
files.select(pin.path);
apdu.resetCommand().
sendCommand(INS_VERIFY, pin.pinReference, 0, false);
} catch (IOException e) {
return PIN_BLOCKED;
}
if (apdu.lastSW == 0x9000) {
return PIN_DISABLED;
}
if (apdu.lastSW == 0x6983) {
return PIN_BLOCKED;
}
return PIN_REQUIRED;
| private PrivateKey | getPrivateKey(byte[] id)Returns private key for given ID.
for (int i = 0; i < PrKeys.length; i++) {
if (Utils.byteMatch(id, PrKeys[i].id)) {
return PrKeys[i];
}
}
return null;
| private TLV | getPublicKey(byte[] id)Returns TLV that contains SubjectPublicKeyInfo structure for
public key.
// try to obtain the key from certificate
for (int i = 0; i < Certificates.length; i++) {
if (! Utils.byteMatch(Certificates[i].id, id)) {
continue;
}
try {
TLV t = files.loadObject(Certificates[i].body);
return t.child.child.skipOptional(0xa0).next.next.next.
next.next.copy();
} catch (IOException e) {
continue;
}
}
/*
there is no certificate for this private key, try to
read public key
*/
for (int i = 0; i < PuKeys.length; i++) {
if (! Utils.byteMatch(PuKeys[i].id, id)) {
continue;
}
try {
files.select(PuKeys[i].body.path);
if (PuKeys[i].body.length == -1) {
PuKeys[i].body.length = files.getCurrrentFileSize();
}
byte[] tmp = files.readData(1, PuKeys[i].body.length,
PuKeys[i].body.offset);
TLV subjectPKInfo = TLV.createSequence();
TLV alg = TLV.createSequence();
subjectPKInfo.setChild(alg);
alg.setChild(TLV.createOID("1.2.840.113549.1.1.1")).
setNext(new TLV(TLV.NULL_TYPE));
alg.setNext(new TLV(TLV.BITSTRING_TYPE, tmp));
return subjectPKInfo;
} catch (IOException e) {
break;
}
}
return null;
| private boolean | init(java.lang.String securityElementID)Reads configuration (EF(TokenInfo) file).
Doesn't throw exceptions.
try {
if (! readTokenInfo(securityElementID)) {
return false;
}
readODF();
loadPINs();
UnusedSpacePath = files.makePath(TLV.createOctetString(
Utils.shortToBytes(UnusedSpace)));
return true;
} catch (IOException te) {
done();
}
return false;
| private void | loadCertificates(boolean loadValues, boolean loadTrusted)Loads attributes of X.509 certificates. Places results into
Certificates array. Places identifiers of all
certificates into certificateIDs vector.
Vector objects = new Vector();
Vector locations = new Vector();
resetLoader(objects, locations, null);
if (loadTrusted) {
loadObjects(TRUSTED_CERTIFICATES_TAG);
}
loadObjects(USEFUL_CERTIFICATES_TAG);
loadObjects(USER_CERTIFICATES_TAG);
Vector k = new Vector();
certificateIDs = new Vector();
for (int i = 0; i < objects.size(); i++) {
TLV t = (TLV) objects.elementAt(i);
// is it x.509 certificate?
if (t.type != TLV.SEQUENCE_TYPE) {
certificateIDs.addElement(t.child.next.child.getValue());
continue;
}
Certificate cert = new Certificate();
k.addElement(cert);
t = t.child; // commonObjectAttributes
cert.label = t.child.getUTF8().trim();
t = t.next;
cert.id = t.child.getValue();
certificateIDs.addElement(cert.id);
TLV v = t.child.next;
if (v != null) {
v = v.skipOptional(TLV.BOOLEAN_TYPE);
if (v != null) {
cert.requestId = v.getValue();
}
}
t = t.next.child.child;
cert.body = files.pathToLocation(t);
if (loadValues) {
cert.cert = files.loadObject(cert.body);
}
cert.header = (Location) locations.elementAt(i);
}
Certificates = new Certificate[k.size()];
k.copyInto(Certificates);
| private void | loadObjects(int tag)Finds all the files for specified type, reads and parses them.
for (int i = 0; i < ODF.size(); i++) {
TLV t = (TLV) ODF.elementAt(i);
if (t.type == tag) {
parseDF(files.makePath(t.child.child));
}
}
| private void | loadPINs()Loads PIN objects and places them into PINs array.
Vector v = new Vector();
resetLoader(v, null, null);
loadObjects(PINS_TAG);
Vector k = new Vector();
for (int i = 0; i < v.size(); i++) {
TLV t = (TLV) v.elementAt(i);
if (t.type != TLV.SEQUENCE_TYPE) { // not a PIN object
continue;
}
PINAttributes pin = new PINAttributes();
k.addElement(pin);
t = t.child; // commonObjectAttributes
pin.label = t.child.getUTF8().trim();
t = t.next; // CommonAuthenticationObjectAttributes
pin.id = t.child.getId();
t = t.next.child.child; // PinAttributes.pinFlags
if (t.checkFlag(0)) {
pin.pinFlags = PINAttributes.FLAG_CASE_SENSITIVE;
}
if (t.checkFlag(5)) {
pin.pinFlags = PINAttributes.FLAG_NEEDS_PADDING;
}
t = t.next;
pin.pinType = t.getEnumerated();
t = t.next;
pin.minLength = t.getInteger();
t = t.next;
pin.storedLength = t.getInteger();
t = t.next;
if (t.type == TLV.INTEGER_TYPE) {
pin.maxLength = t.getInteger();
t = t.next;
} else {
pin.maxLength = pin.storedLength;
}
// this entry is optional, default value is 0
if (t.type == 0x80) {
pin.pinReference = t.getInteger();
t = t.next;
}
pin.padChar = t.getId();
t = t.next.skipOptional(TLV.GEN_TIME_TYPE);
pin.path = files.makePath(t.child);
}
if (k.size() == 0) {
throw new IOException("PINs not found");
}
PINs = new PINAttributes[k.size()];
k.copyInto(PINs);
| private void | loadPrivateKeys()Loads all RSA private keys. Keys are stored in
PrKeys array.
Vector v = new Vector();
resetLoader(v, null, null);
loadObjects(PRIVATE_KEYS_TAG);
Vector k = new Vector();
for (int i = 0; i < v.size(); i++) {
TLV t = (TLV) v.elementAt(i);
if (t.type != TLV.SEQUENCE_TYPE) { // non-RSA key
continue;
}
PrivateKey key = new PrivateKey();
t = t.child; // commonObjectAttributes
key.label = t.child.getUTF8().trim();
key.authId = t.child.next.next.getId();
t = t.next;
TLV m = t.child;
key.id = m.getValue();
m = m.next;
key.authentication = m.checkFlag(2);
key.nonRepudiation = m.checkFlag(9);
m = m.next.skipOptional(TLV.BOOLEAN_TYPE);
key.keyReference = m.getInteger() & 0xff;
// skip PKCS15CommonPrivateKeyAttributes
t = t.next.skipOptional(0xa0);
t = t.child.child;
key.path = files.makePath(t.child);
t = t.next;
key.modulusLength = t.getInteger();
t = t.next;
if (t != null &&
t.type == TLV.INTEGER_TYPE &&
t.getInteger() != RSA_ALGORITHM_ID) {
continue;
}
k.addElement(key);
}
PrKeys = new PrivateKey[k.size()];
k.copyInto(PrKeys);
| private void | loadPublicKeys()Loads all RSA public keys. Stores keys in PuKeys
array.
Vector v = new Vector();
resetLoader(v, null, null);
loadObjects(PUBLIC_KEYS1_TAG);
loadObjects(PUBLIC_KEYS2_TAG);
Vector k = new Vector();
for (int i = 0; i < v.size(); i++) {
TLV t = (TLV) v.elementAt(i);
if (t.type != TLV.SEQUENCE_TYPE) { // non-RSA key
continue;
}
PublicKey key = new PublicKey();
t = t.child; // commonObjectAttributes
t = t.next; // CommonKeyAttributes
key.id = t.child.getValue();
TLV m = t.child.next.next;
if (m.type != TLV.BOOLEAN_TYPE ||
m.data[m.valueOffset] != 0) {
continue; // native, useless for CSR generation
}
// skip PKCS15CommonPublicKeyAttributes
t = t.next.skipOptional(0xa0);
key.body = files.pathToLocation(t.child.child);
k.addElement(key);
}
PuKeys = new PublicKey[k.size()];
k.copyInto(PuKeys);
| private void | parseDF(short[] path)Parses directory file. Places results into vectors specified
resetLoader method.
files.select(path);
doParseDF(files.readFile(), path,
loaderObjects, loaderLocations, loaderFreeBlocks);
| private boolean | putHeaders(java.util.Vector headers)Finds place for new certificates directory entries and registers
all necessary file updates.
Vector holes = null;
for (int i = 0; i < headers.size(); i++) {
try {
if (i == headers.size() - 1) {
holes = new Vector();
resetLoader(null, null, holes);
loadObjects(USEFUL_CERTIFICATES_TAG);
} else
if (i == 0) {
holes = new Vector();
resetLoader(null, null, holes);
loadObjects(USER_CERTIFICATES_TAG);
}
} catch (IOException e) {
// should never happen
return false;
}
TLV header = (TLV) headers.elementAt(i);
byte[] data = header.getDERData();
boolean found = false;
for (int k = 0; k < holes.size(); k++) {
Location l = (Location) holes.elementAt(k);
if (l.length < data.length) {
continue;
}
l.length -= data.length;
update(l.path, l.offset + l.length, data);
// now update the free space after the new record
if (l.length != 0) {
update(l.path, l.offset,
getEmptySpaceHeader(l.length));
found = true;
}
break;
}
if (! found) {
return false;
}
}
return true;
| private Location[] | putObjects(TLV[] path)Finds place for new certificates and registers necessary file
updates.
// find the free space where certificates can be stored
files.select(UnusedSpacePath);
Vector freeSpace = new Vector();
doParseDF(files.readFile(), UnusedSpacePath,
freeSpace, null, null);
Location[] blocks = new Location[freeSpace.size()];
TLV[] records = new TLV[freeSpace.size()];
for (int i = 0; i < freeSpace.size(); i++) {
records[i] = (TLV) freeSpace.elementAt(i);
blocks[i] = files.pathToLocation(records[i].child);
}
Location[] result = new Location[path.length];
for (int j = 0; j < path.length; j++) {
if (path[j] == null) {
continue;
}
byte[] data = path[j].getDERData();
for (int i = 0; i < blocks.length; i++) {
Location block = blocks[i];
if (block.length < data.length) {
continue;
}
block.length -= data.length;
result[j] = new Location(block.path,
block.offset + block.length,
data.length);
update(result[j].path, result[j].offset, data);
// check if PIN is required for this update
TLV t = records[i].child.next;
if (t != null && t.type == TLV.OCTETSTR_TYPE) {
int id;
try {
id = t.getId();
} catch (TLVException e) {
// should never happen
return null;
}
for (int k = 0; k < PINs.length; k++) {
if (PINs[k].id == id) {
updatePIN[k] = true;
}
}
}
// Update length of block
t = records[i].child.child.next.next;
update(UnusedSpacePath, t.valueOffset,
Utils.shortToBytes(block.length));
break;
}
if (result[j] == null) {
return null;
}
}
return result;
| private void | readODF()Reads ODF and sets WIM root directory if necessary.
ODF = new Vector();
resetLoader(ODF, null, null);
parseDF(new short[] {ODFPath});
for (int i = 0; i < ODF.size(); i++) {
TLV t = (TLV) ODF.elementAt(i);
if (t.type != 0xa7) {
continue;
}
t = t.child;
if (t.type != 0xa0) { // not [0]SEQUENCE OF ObjectType
continue;
}
t = t.child.child; // 1st of SEQUENCE OF PKCS15Data
while (t != null) {
if (t.type != TLV.SEQUENCE_TYPE) { // not opaqueDO
t = t.next;
continue;
}
TLV m = t.child.next.child.skipOptional(TLV.UTF8STR_TYPE);
if (m.type != TLV.OID_TYPE ||
! m.valueEquals(WAP_WSG_WIMPATH)) {
t = t.next;
continue;
}
m = t.child.next.next.child;
short[] root = new short[m.length / 2];
for (int j = 0; j < root.length; j++) {
root[j] = Utils.getShort(m.data,
m.valueOffset + j * 2);
}
files.setRoot(root);
break;
}
}
| private boolean | readTokenInfo(java.lang.String securityElementID)Reads and parses EF(TokenInfo).
files.select(TokenInfoPath);
TLV t = new TLV(files.readFile(), 0);
/*
* PKCS15TokenInfo ::= SEQUENCE {
* version INTEGER {v1(0)} (v1,...),
* serialNumber OCTET STRING,
* -manufacturerID PKCS15Label OPTIONAL,
* +label [0] PKCS15Label OPTIONAL,
* +tokenflags PKCS15TokenFlags,
* +seInfo SEQUENCE OF PKCS15SecurityEnvironmentInfo
* OPTIONAL,
* -recordInfo [1] PKCS15RecordInfo OPTIONAL,
* +supportedAlgorithms [2]SEQUENCE OF PKCS15AlgorithmInfo
* OPTIONAL,
* ... -- For future extensions
* }
*/
t = t.child; // version
// it must be integer and it must be 0 (version 1)
if (t.getInteger() != 0) {
return false;
}
t = t.next; // serial number
if (t.type != TLV.OCTETSTR_TYPE) {
return false;
}
serialNumber = Utils.hexNumber(t.data, t.valueOffset, t.length);
// skip optional manufacturerID
t = t.next.skipOptional(TLV.UTF8STR_TYPE);
// it must be label
if (t.type != 0x80) {
return false;
}
String label = t.getUTF8();
if (! (label.startsWith("WIM 1.01") &&
(label.length() == 8 || label.charAt(8) == ' "))) {
return false;
}
if (securityElementID != null &&
label.indexOf(securityElementID) == -1) {
return false;
}
t = t.next; // Token flags. Check if this card is read-only.
readOnly = t.checkFlag(0);
t = t.next; // seInfo
// check if WIM_GENERIC_RSA SE is supported
WIM_GENERIC_RSA_ID = -1;
TLV v = t.child;
while (v != null) {
if (v.child.next.valueEquals(WIM_GENERIC_RSA_OID)) {
WIM_GENERIC_RSA_ID = v.child.getInteger();
break;
}
v = v.next;
}
if (WIM_GENERIC_RSA_ID == -1) {
return false;
}
// skip otional recordInfo
t = t.next.skipOptional(0xa1).child;
// check if RSA signature is supported
boolean supportsSignature = false;
while (t != null) {
TLV m = t.child;
if (m.next.getInteger() == 0) { // 0 - RSA
RSA_ALGORITHM_ID = m.getInteger();
supportsSignature = m.next.next.next.checkFlag(1);
break;
}
t = t.next;
}
return supportsSignature;
| public int | removeCredential(java.lang.String label, TLV isn)Removes credential.
// load existing certificates (excluding trusted - can't delete
// them)
try {
loadCertificates(true, false);
} catch (IOException e) {
return SKIP;
}
Certificate cert = getCertificate(isn.child, isn.child.next);
if (cert == null) {
// there is no such certificate
return SKIP;
}
// IMPL_NOTE: should there be a warning?
// if (! cert.label.trim().equals(label)) {}
// find the certificate chain
Vector chain = getChain(cert, null, false);
// this chain can have common certificates with some other
// chains, in this case only part of the chain should be deleted
int count = chain.size();
check:
for (int i = 1; i < chain.size(); i++) {
for (int k = 0; k < Certificates.length; k++) {
if (Certificates[k] != chain.elementAt(i - 1) &&
Certificates[k].isIssuedBy((Certificate)
chain.elementAt(i))) {
count = i;
break check;
}
}
}
try {
if (MessageDialog.showMessage(securityToken,
Resource.getString(ResourceConstants.AMS_CONFIRMATION),
Resource.getString(ResourceConstants
.JSR177_CERTIFICATE_DELETED) +
"\n\n" +
// "Label: "
Resource.getString(ResourceConstants.
JSR177_CERTIFICATE_LABEL) + ": " +
cert.label + "\n\n" +
Certificate.getInfo(cert.cert) + "\n\n",
true) == Dialog.CANCELLED) {
return CANCEL;
}
} catch (InterruptedException e) {
return CANCEL;
}
startUpdate();
try {
doRemove(chain, count);
int pinStatus = checkPIN(PINs[0]);
if (pinStatus == PIN_CANCELLED) {
return CANCEL;
}
if (pinStatus == PIN_BLOCKED) {
throw new SecurityException("PIN blocked");
}
if (pinStatus != PIN_DISABLED) {
return ERROR;
}
doUpdate();
} catch (IOException e) {
return ERROR;
}
// typeInfo("RemoveCredential");
return SUCCESS;
| private void | resetLoader(java.util.Vector objects, java.util.Vector locations, java.util.Vector freeBlocks)Initialises object loader.
loaderObjects = objects;
loaderLocations = locations;
loaderFreeBlocks = freeBlocks;
| private java.util.Vector | selectChain(java.util.Vector chains)Allows user to select certificate or cancel signature operation.
String[] labels = new String[chains.size()];
for (int i = 0; i < chains.size(); i++) {
labels[i] = ((Certificate)
((Vector) chains.elementAt(i)).elementAt(0)).label;
}
int chainIndex = -1;
try {
if (chains.size() == 1) {
// if only one chain is found show certificate label to
// the user
if (MessageDialog.showMessage(securityToken,
Resource.getString(ResourceConstants
.AMS_CONFIRMATION),
Resource.getString(ResourceConstants
.JSR177_CERTIFICATE_USED) +
labels[0], true) != Dialog.CANCELLED) {
chainIndex = 0;
}
} else {
// if more than one chain is found ask user to choose
// one of them
chainIndex = MessageDialog.chooseItem(securityToken,
Resource.getString(ResourceConstants
.JSR177_SELECT_CERTIFICATE),
Resource.getString(ResourceConstants
.JSR177_CERTIFICATES_AVAILABLE),
labels);
}
} catch (InterruptedException e) {}
return (chainIndex == -1) ? null :
(Vector) chains.elementAt(chainIndex);
| private void | setBlockLength(TLV t, int length)Modify length of block in record of EF(UnusedSpace).
t = t.child.child.next.next;
update(UnusedSpacePath,
t.valueOffset, Utils.shortToBytes(length));
| private void | setBlockOffset(TLV t, int offset)Modify offset in record of EF(UnusedSpace).
t = t.child.child.next;
update(UnusedSpacePath,
t.valueOffset, Utils.shortToBytes(offset));
| private byte[] | signData(PrivateKey key, byte[] data)Sign given data using given key.
// calculate SHA-1 digest
byte[] tmp = Utils.getHash(data, 0, data.length);
// MSE - RESTORE
apdu.resetCommand().
sendCommand(INS_MSE, 0xf300 | WIM_GENERIC_RSA_ID, 0, true);
// MSE - SET
apdu.resetCommand().
putByte(0x84). // key reference tag
putByte(0x1). // length
putByte(key.keyReference). // value
putByte(0x81). // private key path tag
putByte(key.path.length * 2); // length
for (int i = 0; i < key.path.length; i++) { // value
apdu.putShort(key.path[i]);
}
apdu.sendCommand(INS_MSE, 0x41b6, 0, true);
// sign the data
tmp = apdu.resetCommand().
putBytes(DigestInfoHeader, 0, DigestInfoHeader.length).
putBytes(tmp, 0, 20).
sendCommand(INS_PSO, 0x9e9a);
byte[] sign = new byte[tmp.length - 1];
System.arraycopy(tmp, 0, sign, 1, tmp.length - 2);
return sign;
| private void | startUpdate()Initialises the new update.
updateLocations = new Vector();
updateData = new Vector();
updatePIN = new boolean[PINs.length];
updatePIN[0] = true;
| private void | update(short[] path, int offset, byte[] data)Registers file modification.
updateLocations.addElement(new Location(path, offset, 0));
updateData.addElement(data);
|
|