use of org.openecard.common.tlv.TLV in project open-ecard by ecsec.
the class CardRecognitionImpl method checkDataObject.
private boolean checkDataObject(DataMaskType matcher, TLV result) {
byte[] tag = matcher.getTag();
DataMaskType nextMatcher = matcher.getDataObject();
// this function only works with tag and dataobject
if (tag == null || nextMatcher == null) {
return false;
}
long tagNum = ByteUtils.toLong(tag);
List<TLV> chunks = result.findNextTags(tagNum);
for (TLV next : chunks) {
boolean outcome;
if (nextMatcher.getMatchingData() != null) {
outcome = checkMatchingData(nextMatcher.getMatchingData(), next.getValue());
} else {
outcome = checkDataObject(nextMatcher, next.getChild());
}
// evaluate outcome
if (outcome == true) {
return true;
}
}
// no match
return false;
}
use of org.openecard.common.tlv.TLV in project open-ecard by ecsec.
the class SecureMessaging method decrypt.
/**
* Decrypt the APDU.
*
* @param response the response
* @param secureMessagingSSC the secure messaging ssc
* @return the byte[]
* @throws Exception the exception
*/
private byte[] decrypt(byte[] response, byte[] secureMessagingSSC) throws Exception {
ByteArrayInputStream bais = new ByteArrayInputStream(response);
ByteArrayOutputStream baos = new ByteArrayOutputStream(response.length - 10);
// Status bytes of the response APDU. MUST be 2 bytes.
byte[] statusBytes = new byte[2];
// Padding-content indicator followed by cryptogram 0x87.
byte[] dataObject = null;
// Cryptographic checksum 0x8E. MUST be 8 bytes.
byte[] macObject = new byte[8];
/*
* Read APDU structure
* Case 1: DO99|DO8E|SW1SW2
* Case 2: DO87|DO99|DO8E|SW1SW2
* Case 3: DO99|DO8E|SW1SW2
* Case 4: DO87|DO99|DO8E|SW1SW2
*/
byte tag = (byte) bais.read();
// Read data object (OPTIONAL)
if (tag == (byte) 0x87) {
int size = bais.read();
if (size > 0x80) {
byte[] sizeBytes = new byte[size & 0x0F];
bais.read(sizeBytes, 0, sizeBytes.length);
size = new BigInteger(1, sizeBytes).intValue();
}
// Skip encryption header
bais.skip(1);
dataObject = new byte[size - 1];
bais.read(dataObject, 0, dataObject.length);
tag = (byte) bais.read();
}
// Read processing status (REQUIRED)
if (tag == (byte) 0x99) {
if (bais.read() == (byte) 0x02) {
bais.read(statusBytes, 0, 2);
tag = (byte) bais.read();
}
} else {
throw new IOException("Malformed Secure Messaging APDU");
}
// Read MAC (REQUIRED)
if (tag == (byte) 0x8E) {
if (bais.read() == (byte) 0x08) {
bais.read(macObject, 0, 8);
}
} else {
throw new IOException("Malformed Secure Messaging APDU");
}
// Only 2 bytes status should remain
if (bais.available() != 2) {
throw new IOException("Malformed Secure Messaging APDU");
}
// Calculate MAC for verification
CMac cmac = getCMAC(secureMessagingSSC);
byte[] mac = new byte[16];
synchronized (cmac) {
ByteArrayOutputStream macData = new ByteArrayOutputStream();
// Write padding-content
if (dataObject != null) {
TLV paddedDataObject = new TLV();
paddedDataObject.setTagNumWithClass((byte) 0x87);
paddedDataObject.setValue(ByteUtils.concatenate((byte) 0x01, dataObject));
macData.write(paddedDataObject.toBER());
}
// Write status bytes
TLV statusBytesObject = new TLV();
statusBytesObject.setTagNumWithClass((byte) 0x99);
statusBytesObject.setValue(statusBytes);
macData.write(statusBytesObject.toBER());
byte[] paddedData = pad(macData.toByteArray(), 16);
cmac.update(paddedData, 0, paddedData.length);
cmac.doFinal(mac, 0);
mac = ByteUtils.copy(mac, 0, 8);
}
// Verify MAC
if (!ByteUtils.compare(mac, macObject)) {
throw new GeneralSecurityException("Secure Messaging MAC verification failed");
}
// Decrypt data
if (dataObject != null) {
Cipher c = getCipher(secureMessagingSSC, Cipher.DECRYPT_MODE);
byte[] data_decrypted = c.doFinal(dataObject);
baos.write(unpad(data_decrypted));
}
// Add status code
baos.write(statusBytes);
return baos.toByteArray();
}
use of org.openecard.common.tlv.TLV in project open-ecard by ecsec.
the class AuthenticationToken method getMACObject.
/**
* Calculates the data for the authentication token.
*
* @param key Key
* @return data object for token
*/
private byte[] getMACObject(byte[] key) throws GeneralSecurityException {
byte[] ret = null;
try {
TLV keyObject = new TLV();
keyObject.setTagNumWithClass((byte) 0x86);
keyObject.setValue(ByteUtils.cutLeadingNullBytes(key));
TLV oidObject = new TLV();
oidObject.setTagNumWithClass((byte) 0x06);
oidObject.setValue(ObjectIdentifierUtils.getValue(pi.getProtocol()));
oidObject.addToEnd(keyObject);
TLV macObject = new TLV();
macObject.setTagNum((byte) 0x49);
macObject.setTagClass(TagClass.APPLICATION);
macObject.setChild(oidObject);
ret = macObject.toBER(true);
} catch (Throwable e) {
logger.error(e.getMessage(), e);
throw new GeneralSecurityException(e);
}
return ret;
}
use of org.openecard.common.tlv.TLV in project open-ecard by ecsec.
the class AuthenticationToken method verifyToken.
/**
* Verify the authentication token by the PICC and extract Certificate Authority Reference (CAR).
*
* @param T_PICC Token from the PICC
* @param specifiedCHAT true if PACE is used with a CHAT
* @return true if T_PICC is equal to my T_PICC
* @throws GeneralSecurityException
*/
public boolean verifyToken(byte[] T_PICC, boolean specifiedCHAT) throws GeneralSecurityException {
try {
TLV dataSet = TLV.fromBER(T_PICC);
// set of dynamic authentication data
if (dataSet.getTagNumWithClass() != 0x7C) {
throw new GeneralSecurityException("The returned object is not a set of dynamic authentication data.");
}
// Authentication Token
List<TLV> authTokens = dataSet.findChildTags(0x86);
if (authTokens.isEmpty()) {
String msg = "Authentication Token is missing in set of dynamic authentication data.";
throw new GeneralSecurityException(msg);
} else if (authTokens.size() > 1) {
String msg = "Authentication Token is present multiple times in set of dynamic authentication data.";
throw new GeneralSecurityException(msg);
} else {
byte[] newToken = authTokens.get(0).getValue();
if (!ByteUtils.compare(newToken, token)) {
throw new GeneralSecurityException("Can not verify authentication token.");
}
}
// CAR
if (specifiedCHAT) {
// current CAR
List<TLV> car1 = dataSet.findChildTags(0x87);
if (car1.isEmpty()) {
String msg = "Current CAR is missing in set of dynamic authentication data.";
throw new GeneralSecurityException(msg);
} else if (car1.size() > 1) {
String msg = "Current CAR is present multiple times in set of dynamic authentication data.";
throw new GeneralSecurityException(msg);
} else {
currentCAR = car1.get(0).getValue();
verifyCAR("Current CAR", currentCAR);
}
// last CAR
List<TLV> car2 = dataSet.findChildTags(0x88);
if (car2.size() > 1) {
String msg = "Previous CAR is present multiple times in set of dynamic authentication data.";
throw new GeneralSecurityException(msg);
} else if (car2.size() == 1) {
previousCAR = car2.get(0).getValue();
verifyCAR("Previous CAR", previousCAR);
}
}
} catch (TLVException ex) {
throw new GeneralSecurityException("Given data is not a valid ASN.1 object.", ex);
}
return true;
}
use of org.openecard.common.tlv.TLV in project open-ecard by ecsec.
the class FCP method toString.
// TODO: implement further tags in FCP
/**
* Create a string from the object which contains all collected information.
*
* @param prefix
* @return A string containing all collected information.
*/
public String toString(String prefix) {
StringBuilder b = new StringBuilder(4096);
String indent = prefix + " ";
String subindent = indent + " ";
b.append(prefix);
b.append("FCP:\n");
b.append(indent);
b.append("num-bytes=");
b.append(numBytes);
b.append(" num-bytes-structure=");
b.append(numBytesStructure);
b.append("\n");
b.append(dataElements.toString(indent));
b.append("\n");
b.append(indent);
b.append("File-Identifiers:\n");
for (byte[] next : fileIdentifiers) {
b.append(subindent);
b.append(ByteUtils.toHexString(next));
b.append("\n");
}
b.append("DF-Names:\n");
for (byte[] next : dfNames) {
b.append(subindent);
b.append(ByteUtils.toHexString(next));
b.append("\n");
}
// shortEfIdentifier
if (shortEfIdentifier != null) {
b.append(indent);
b.append("short-EF-identifier: ");
b.append(ByteUtils.toHexString(shortEfIdentifier));
b.append("\n");
}
// lifeCycleStatusByte
// securityAttributeReferenceExpanded
// securityAttributeCompact
// securityEnvironmentTemplateEfs
// channelSecurityAttribute
// securityAttributeTemplateForDataObject
// securityAttributeTemplateProprietary
// dataObjectTemplates
b.append(indent);
b.append("DataObjectTemplates:\n");
for (TLV next : dataObjectTemplates) {
b.append(subindent);
b.append("DataObjectTemplate:");
b.append(next.toString(subindent + " "));
b.append("\n");
}
return b.toString();
}
Aggregations