diff options
| author | tzefferer <tzefferer@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4> | 2010-11-08 14:07:45 +0000 | 
|---|---|---|
| committer | tzefferer <tzefferer@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4> | 2010-11-08 14:07:45 +0000 | 
| commit | 5c002cd206ae4a024e445a16747d80fe8a5535e2 (patch) | |
| tree | 1ce717d7ffa9e3b705c9591d68329cdffcfbd98d /smcc/src | |
| parent | 7229336487111d6b17fb2693e6a9ef52283c08c9 (diff) | |
| download | mocca-5c002cd206ae4a024e445a16747d80fe8a5535e2.tar.gz mocca-5c002cd206ae4a024e445a16747d80fe8a5535e2.tar.bz2 mocca-5c002cd206ae4a024e445a16747d80fe8a5535e2.zip | |
git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@822 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4
Diffstat (limited to 'smcc/src')
3 files changed, 306 insertions, 63 deletions
| diff --git a/smcc/src/main/java/at/gv/egiz/smcc/DNIeCard.java b/smcc/src/main/java/at/gv/egiz/smcc/DNIeCard.java index 768ac959..ccb463a5 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/DNIeCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/DNIeCard.java @@ -1,5 +1,25 @@ +/*
 +* Copyright 2009 Federal Chancellery Austria and
 +* Graz University of Technology
 +*
 +* Licensed under the Apache License, Version 2.0 (the "License");
 +* you may not use this file except in compliance with the License.
 +* You may obtain a copy of the License at
 +*
 +*     http://www.apache.org/licenses/LICENSE-2.0
 +*
 +* Unless required by applicable law or agreed to in writing, software
 +* distributed under the License is distributed on an "AS IS" BASIS,
 +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 +* See the License for the specific language governing permissions and
 +* limitations under the License.
 +*/
 +
  package at.gv.egiz.smcc;
 +import iaik.me.asn1.ASN1;
 +
 +import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.security.MessageDigest;
 @@ -25,6 +45,9 @@ public class DNIeCard extends AbstractSignatureCard implements SignatureCard {  			(byte) 0x72, (byte) 0x2E, (byte) 0x46, (byte) 0x69, (byte) 0x6C,
  			(byte) 0x65 };
 +	private final String SIG_KEY_NAME = "KprivFirmaDigital";
 +	private final String SIG_CERT_NAME = "CertFirmaDigital";
 +	
  	protected PinInfo pinInfo = new PinInfo(8, 16,
  			"[0-9A-Za-z_<>!()?%\\-=&+\\.]", "at/gv/egiz/smcc/DNIeCard",
  			"sig.pin", (byte) 0x00, new byte[] {}, PinInfo.UNKNOWN_RETRIES);
 @@ -52,9 +75,13 @@ public class DNIeCard extends AbstractSignatureCard implements SignatureCard {  			}
  		try {
 +			
 +			byte[] prKdf = executeReadPrKDF(channel);
 +			byte[] keyId = getKeyIdFromASN1File(prKdf);
 +			
  			verifyPINLoop(channel, pinInfo, pinGUI);
 -			secureChannel.executeSecureManageSecurityEnvironment(channel);
 +			secureChannel.executeSecureManageSecurityEnvironment(channel, keyId);
  			MessageDigest md;
  			try {
 @@ -88,14 +115,30 @@ public class DNIeCard extends AbstractSignatureCard implements SignatureCard {  		CardChannel channel = getCardChannel();
 -		if (!secureChannel.isEstablished())
 +		if (!secureChannel.isEstablished()) {
  			try {
  				secureChannel.establish(channel);
  			} catch (CardException e) {
  				log.debug("Error establishing secure channel to card.", e);
  			}
 +		}
 +		byte[] certId = null;
 +		
 +		try {
 +			// read CDF file
 +			byte[] cdf = executeReadCDF(channel);
 +			
 +			// extract certificate id from ASN1 data structure
 +			certId = getCertIdFromASN1File(cdf);
 +			
 +		} catch (CardException e1) {
 +
 +			log.error("Error reading ASN.1 data!");
 +			e1.printStackTrace();
 +		}
 +						
  		log.debug("Try to read certificate..");
  		try {
 @@ -112,11 +155,11 @@ public class DNIeCard extends AbstractSignatureCard implements SignatureCard {  			secureChannel.executeSecureSelect(channel, apdu);
 -			// select 7005
 +			// select cert id
  			byte[] apdu2 = new byte[] {
  			(byte) 0x00, (byte) 0xA4, (byte) 0x00, (byte) 0x00, (byte) 0x02,
 -					(byte) 0x70, (byte) 0x05 };
 +			certId[certId.length-2], certId[certId.length-1] };
  			byte[] fci = secureChannel.executeSecureSelect(channel, apdu2);
 @@ -126,14 +169,11 @@ public class DNIeCard extends AbstractSignatureCard implements SignatureCard {  			byte[] data = secureChannel.executeSecureReadBinary(channel,
  					sizeHi, sizeLo);
 -			int uncompressedDataLen = getUncompressedDataLength(data);
 -
  			byte[] compressedWithoutHeader = new byte[data.length - 8];
  			System.arraycopy(data, 8, compressedWithoutHeader, 0,
  					compressedWithoutHeader.length);
 -			result = decompressData(compressedWithoutHeader,
 -					uncompressedDataLen);
 +			result = decompressData(compressedWithoutHeader);
  		} catch (CardException e) {
 @@ -218,37 +258,218 @@ public class DNIeCard extends AbstractSignatureCard implements SignatureCard {  		secureChannel.executeSecureSelect(channel, apdu);
  	}
 -	private int getUncompressedDataLength(byte[] data) {
 -
 -		byte len0 = data[0];
 -		byte len1 = data[1];
 -		byte len2 = data[2];
 -		byte len3 = data[3];
 +	private byte[] executeReadCDF(CardChannel channel) throws CardException {
 +		
 +		return executeReadFile(channel, new byte[]{(byte)0x50,(byte)0x15,(byte)0x60,(byte)0x04});		
 +	}	
 +	
 +	private byte[] executeReadPrKDF(CardChannel channel) throws CardException {
 +		
 +		return executeReadFile(channel, new byte[]{(byte)0x50,(byte)0x15,(byte)0x60,(byte)0x01});
 +	}
 +	
 +	private byte[] getKeyIdFromASN1File(byte[] file) throws CardException {
 +
 +		// split file in two records
 +		int record1Length = getRecordLength(file, 1);
 +		
 +		byte[] record1 = new byte[record1Length];
 +		byte[] record2 = new byte[file.length - record1.length];
 +		
 +		System.arraycopy(file, 0, record1, 0, record1.length);
 +		System.arraycopy(file, record1.length, record2, 0, record2.length);
 +		
 +		byte[] keyId = new byte[2];
 +		
 +		try {
 +			ASN1 asn1_1 = new ASN1(record1);
 +			ASN1 asn1_2 = new ASN1(record2);
 +
 +			if(asn1_1.getElementAt(0).getElementAt(0).gvString().equalsIgnoreCase(SIG_KEY_NAME)) {
 +				
 +				byte[] data = asn1_1.getElementAt(2).gvByteArray();
 +				
 +				keyId[0] = data[9];
 +				keyId[1] = data[10];
 +			}
 -		int a = len0;
 -		int b = len1 * 256;
 -		int c = len2 * 256 * 256;
 -		int d = len3 * 256 * 256 * 256;
 +			else if(asn1_2.getElementAt(0).getElementAt(0).gvString().equalsIgnoreCase(SIG_KEY_NAME)) {
 +				
 +				byte[] data = asn1_2.getElementAt(2).gvByteArray();
 +				
 +				keyId[0] = data[9];
 +				keyId[1] = data[10];
 +			}
 +			
 +		} catch (Exception e) {
 -		return a + b + c + d;
 +			throw new CardException("Error getting ASN1 data.", e);
 +		}		
 +		
 +		return keyId;
  	}
 -
 -	private byte[] decompressData(byte[] input, int len) throws CardException {
 +	
 +	private byte[] getCertIdFromASN1File(byte[] file) throws CardException {
 +
 +		int record1Length = getRecordLength(file, 1);
 +		
 +		// split file in two records
 +		byte[] record1 = new byte[record1Length];
 +		byte[] record2 = new byte[file.length - record1.length];
 +		
 +		System.arraycopy(file, 0, record1, 0, record1.length);
 +		System.arraycopy(file, record1.length, record2, 0, record2.length);
 +		
 +		byte[] certId = null;
 +		
 +		try {
 +			ASN1 asn1_1 = new ASN1(record1);
 +			ASN1 asn1_2 = new ASN1(record2);
 +	
 +			if(asn1_1.getElementAt(0).getElementAt(0).gvString().equalsIgnoreCase(SIG_CERT_NAME)) {
 +			
 +				certId = retrieveCertId(asn1_1.getElementAt(2).gvByteArray());				
 +			}
 +			
 +			if(asn1_2.getElementAt(0).getElementAt(0).gvString().equalsIgnoreCase(SIG_CERT_NAME)) {
 +				
 +				certId = retrieveCertId(asn1_2.getElementAt(2).gvByteArray());			
 +			}
 +			
 +		} catch (Exception e) {
 +
 +			throw new CardException("Error getting ASN1 data.", e);
 +		}	
 +	
 +		return certId;
 +	}	
 +	
 +	private byte[] retrieveCertId(byte[] data) throws CardException {
 +		
 +		ASN1 contextSpecific = getASN1WithinContextSpecific(data);
 +		try {
 +			return contextSpecific.getElementAt(0).getElementAt(0).gvByteArray();
 +		} catch (IOException e) {
 +			throw new CardException("Error retrieving certificate ID from ASN1 data.", e);
 +		}
 +	}
 +	
 +	private ASN1 getASN1WithinContextSpecific(byte[] data) throws CardException {
 +		
 +		byte first = data[0];
 +		byte lengthOfLength = 0;
 +		
 +		if(first < 0) {
 +			
 +			lengthOfLength = (byte)(first & (byte)0x7F);
 +			lengthOfLength = (byte)(lengthOfLength +1);
 +		} else {
 +			
 +			lengthOfLength = 1;
 +		}
 +		
 +		byte[] asn1data = new byte[data.length - lengthOfLength];
 +		System.arraycopy(data, lengthOfLength, asn1data, 0, asn1data.length);
 +				
 +		try {
 +			return new ASN1(asn1data);
 +		} catch (IOException e) {
 +			throw new CardException("Error getting ASN1 structure.", e);
 +		}
 +	}	
 +	
 +	private int getRecordLength(byte[] data, int startOfLength) {
 +		
 +		byte lengthStartByte = data[startOfLength];
 +		
 +		if(lengthStartByte < 0) {
 +			// we have more than one length byte
 +			byte lengthOfLength = (byte)(lengthStartByte & (byte)0x7F);
 +			
 +			byte[] lengthValues = new byte[lengthOfLength];			
 +			System.arraycopy(data, startOfLength+1, lengthValues, 0, lengthOfLength);
 +			
 +			int result = 0;
 +			
 +			for(int i=0; i<lengthValues.length; i++) {
 +				
 +				result = (result + byteToInt(lengthValues[lengthValues.length-1-i]) * (int)Math.pow(256, i));
 +			}
 +			
 +			return result + startOfLength + lengthOfLength + 1; // defined length + tag byte + length bytes
 +			
 +		} else {
 +			
 +			return (int)lengthStartByte + startOfLength + 1; // defined length + tag byte + length byte
 +		}
 +		
 +	}
 +	
 +	private int byteToInt(byte b) {
 +		
 +		return b < 0 ? b + 256 : b;
 +		
 +	}
 +	
 +	private byte[] executeReadFile(CardChannel channel, byte[] path) throws CardException {
 +		
 +		log.debug("Executing secure read File command..");
 +		
 +		executeSecureSelectMasterFile(channel);
 +		
 +		// Select DF 
 +		byte[] apdu_1 = new byte[] {
 +				
 +				(byte)0x00,   	// CLA 
 +				(byte)0xA4, 	// INS
 +				(byte)0x00, 	// P1
 +				(byte)0x00, 	// P2
 +				(byte)0x02, 	// Lc
 +				path[0], 
 +				path[1] 
 +		};
 +		
 +		secureChannel.executeSecureSelect(channel, apdu_1);
 +		
 +		// Select EF 
 +		byte[] apdu_2 = new byte[] {
 +				
 +				(byte)0x00,   	// CLA 
 +				(byte)0xA4, 	// INS
 +				(byte)0x00, 	// P1
 +				(byte)0x00, 	// P2
 +				(byte)0x02, 	// Lc
 +				path[2], 
 +				path[3] 
 +		};
 +		
 +		byte[] fci = secureChannel.executeSecureSelect(channel, apdu_2);		
 +		byte[] file = secureChannel.executeSecureReadBinary(channel, fci[7], fci[8]);		
 +		
 +		return file;		
 +	}	
 +
 +	private byte[] decompressData(byte[] input) throws CardException {
  		Inflater decompresser = new Inflater();
  		decompresser.setInput(input, 0, input.length);
 -		byte[] result = new byte[len];
 -
 +		byte[] buffer = new byte[256];
 +		ByteArrayOutputStream bos = new ByteArrayOutputStream();
 +		
  		try {
 -			decompresser.inflate(result);
 -			decompresser.end();
 -
 -			return result;
 +			while(!decompresser.finished()) {
 +			
 +				int numBytes = decompresser.inflate(buffer);
 +				bos.write(buffer, 0, numBytes);
 +			}
 +			decompresser.end();
 +			
  		} catch (DataFormatException e) {
  			throw new CardException("Error decompressing file.", e);
  		}
 -	}
 +		return bos.toByteArray();
 +	}
  }
 diff --git a/smcc/src/main/java/at/gv/egiz/smcc/DNIeCardSecureChannel.java b/smcc/src/main/java/at/gv/egiz/smcc/DNIeCardSecureChannel.java index 5f789922..da63bec2 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/DNIeCardSecureChannel.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/DNIeCardSecureChannel.java @@ -1,3 +1,20 @@ +/*
 +* Copyright 2009 Federal Chancellery Austria and
 +* Graz University of Technology
 +*
 +* Licensed under the Apache License, Version 2.0 (the "License");
 +* you may not use this file except in compliance with the License.
 +* You may obtain a copy of the License at
 +*
 +*     http://www.apache.org/licenses/LICENSE-2.0
 +*
 +* Unless required by applicable law or agreed to in writing, software
 +* distributed under the License is distributed on an "AS IS" BASIS,
 +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 +* See the License for the specific language governing permissions and
 +* limitations under the License.
 +*/
 +
  package at.gv.egiz.smcc;
  import java.io.ByteArrayInputStream;
 @@ -188,8 +205,6 @@ public class DNIeCardSecureChannel {  	private final byte[] IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  			0x00, 0x00 };
 -	private final byte[] KEY_ID = new byte[] { (byte) 0x01, (byte) 0x02 };
 -
  	private final byte[] HASH_PADDING = new byte[] {
  	(byte) 0x30, (byte) 0x21, (byte) 0x30, (byte) 0x09, (byte) 0x06,
 @@ -220,10 +235,12 @@ public class DNIeCardSecureChannel {  	public void establish(CardChannel channel) throws CardException {
 +		log.debug("Setting up secure channel to crd..");
 +		
  		// get chip info
  		this.snIcc = executeGetChipInfo(channel);
 -		// get certificates to establish secure channel
 +		// get card certificates to establish secure channel
  		this.intermediateCert = executeReadSecureChannelCertificate(channel,
  				SECURE_CHANNEL_INTERMEDIAT_CERT_ID);
  		this.componentCert = executeReadSecureChannelCertificate(channel,
 @@ -288,20 +305,21 @@ public class DNIeCardSecureChannel {  	}
 -	public void executeSecureManageSecurityEnvironment(CardChannel channel)
 +	public void executeSecureManageSecurityEnvironment(CardChannel channel, byte[] id)
  			throws CardException {
  		log.debug("Manage Security Environment..");
 -		byte[] apdu = new byte[7 + KEY_ID.length];
 +		byte[] apdu = new byte[7 + 2];
  		apdu[0] = (byte) 0x00;
  		apdu[1] = (byte) 0x22;
  		apdu[2] = (byte) 0x41;
  		apdu[3] = (byte) 0xB6;
 -		apdu[4] = (byte) (KEY_ID.length + 2);
 +		apdu[4] = (byte) (2 + 2);
  		apdu[5] = (byte) 0x84; // Tag
 -		apdu[6] = (byte) KEY_ID.length; // Length
 -		System.arraycopy(KEY_ID, 0, apdu, 7, KEY_ID.length);
 +		apdu[6] = (byte) 0x02; // Length
 +		apdu[7] = id[0]; // ID
 +		apdu[8] = id[1]; // ID
  		byte[] securedAPDU = getSecuredAPDU(apdu);
 @@ -479,9 +497,6 @@ public class DNIeCardSecureChannel {  		System.arraycopy(encrypted, 0, encapsulated, 3, encrypted.length);
  		// calculate MAC
 -
 -		// prepare CLA byte
 -
  		byte encCLA = (byte) (cla | (byte) 0x0C);
  		byte[] encHeader = new byte[] { encCLA, ins, p1, p2 };
  		byte[] paddedHeader = applyPadding(BLOCK_LENGTH, encHeader);
 @@ -733,8 +748,6 @@ public class DNIeCardSecureChannel {  		byte[] decryptedResponse = verifyAndDecryptSecuredResponseAPDU(data);
 -		log.debug("Read plain data: " + formatByteArray(decryptedResponse));
 -
  		return decryptedResponse;
  	}
 @@ -869,7 +882,7 @@ public class DNIeCardSecureChannel {  		byte[] prnd2 = getRandomBytes(this.prndLength);
  		byte[] kIfd = getRandomBytes(32);
 -
 +		
  		// compute hash
  		byte[] hashData = new byte[prnd2.length + kIfd.length
  				+ cardChallenge.length + BLOCK_LENGTH];
 @@ -888,9 +901,9 @@ public class DNIeCardSecureChannel {  		System.arraycopy(snIcc, 0, hashData, prnd2.length + kIfd.length
  				+ cardChallenge.length + snPadding, snIcc.length);
 -
 +		
  		byte[] digest = computeSHA1Hash(hashData);
 -
 +		
  		// prepare data to be encrypted
  		byte[] plain = new byte[2 + prnd2.length + kIfd.length + digest.length];
 @@ -906,17 +919,17 @@ public class DNIeCardSecureChannel {  		// encrypt plain data
  		RSAPrivateKey terminalPrivateKey = createRSAPrivateKey(TERMINAL_MODULO,
  				TERMINAL_PRIVEXP);
 -
 +		
  		byte[] encResult = null;
  		try {
  			encResult = rsaEncrypt(terminalPrivateKey, plain);
  		} catch (Exception e) {
 -
 +			e.printStackTrace();
  			throw new CardException("Error encrypting authentication data.", e);
  		}
 -		// apply MIN function
 -		BigInteger sig = new BigInteger(encResult);
 +		// apply MIN function	
 +		BigInteger sig = createUnsignedBigInteger(encResult);
  		BigInteger mod = new BigInteger(TERMINAL_MODULO, 16);
  		BigInteger diff = mod.subtract(sig);
 @@ -932,10 +945,11 @@ public class DNIeCardSecureChannel {  		try {
  			authData = rsaEncrypt(cardPubKey, sigMin.toByteArray());
  		} catch (Exception e) {
 -
 +			e.printStackTrace();
  			throw new CardException("Error encrypting authentication data.");
  		}
 +		log.debug("Sending computed cryptogram to card..");
  		// send auth data to card
  		// BE CAREFUL WITH THAT! EXT-AUTH METHOD MAY GET BLOCKED!
  		if (executeExternalAuthenticate(channel, authData)) {
 @@ -962,6 +976,8 @@ public class DNIeCardSecureChannel {  	private void performInternalAuthentication(CardChannel channel)
  			throws CardException {
 +		log.debug("Starting internal authentication..");
 +		
  		byte[] randomBytes = getRandomBytes(BLOCK_LENGTH);
  		byte[] challengeData = new byte[randomBytes.length
  				+ TERMINAL_CHALLENGE_TAIL.length];
 @@ -991,7 +1007,6 @@ public class DNIeCardSecureChannel {  		// This method verifies the card's component and intermediate
  		// certificates cryptographically.
 -		// TODO: Revocation checking (cannot be done now since CRL URLs in certificates seem to be incorrect)
  		RSAPublicKey rootPubKey = createRSAPublicKey(ROOT_CA_MODULO,
  				ROOT_CA_PUBEXP);
 @@ -1004,8 +1019,7 @@ public class DNIeCardSecureChannel {  			intermediate.verify(rootPubKey);
  		} catch (Exception e) {
 -			log.error("Certificate verification failed.");
 -			e.printStackTrace();
 +			throw new CardException("Certificate verification failed.", e);			
  		}
  	}
 @@ -1044,27 +1058,27 @@ public class DNIeCardSecureChannel {  		if (sig == null) {
 -			throw new CardException("Invalid decryption result - null.");
 +			throw new CardException("Invalid decryption result: null.");
  		} else {
  			if (sig[0] == (byte) 0x6A && sig[sig.length - 1] == (byte) 0xBC) {
  				// Obtained response from card was obviously SIG - nothing else
 -				// to do here
 +				// to do here so far
  			} else {
 -				// Obtained response from card was obviously N.ICC-SIG -
 +				// Obtained response from card was probably N.ICC-SIG -
  				// compute N.ICC-SIG and decrypt result again
  				RSAPublicKey rsaPubKey = (RSAPublicKey) pubKey;
  				BigInteger mod = rsaPubKey.getModulus();
 -				BigInteger sigVal = new BigInteger(plain);
 +				BigInteger sigVal = createUnsignedBigInteger(plain);
  				BigInteger substractionResult = mod.subtract(sigVal);
  				byte[] encrypted = substractionResult.toByteArray();
 -				// necessary as substraction result seems to contain one leading
 +				// necessary if substraction result contains leading
  				// zero byte
  				byte[] trimmed = new byte[128];
  				System.arraycopy(encrypted, encrypted.length - 128, trimmed, 0,
 @@ -1148,8 +1162,6 @@ public class DNIeCardSecureChannel {  			log.debug("FAILED: " + Integer.toHexString(resp.getSW()));
  		}
 -		log.debug("Read chip info: " + formatByteArray(resp.getData()));
 -
  		return resp.getData();
  	}
 @@ -1430,6 +1442,16 @@ public class DNIeCardSecureChannel {  		return result;
  	}
 +	private BigInteger createUnsignedBigInteger(byte[] data) {
 +		
 +		byte[] unsigned = new byte[data.length+1];
 +		unsigned[0] = (byte)0x00;
 +		System.arraycopy(data, 0, unsigned, 1, data.length);
 +		
 +		return new BigInteger(unsigned);
 +		
 +	}	
 +	
  	private RSAPrivateKey createRSAPrivateKey(String mod, String privExponent)
  			throws CardException {
 @@ -1473,7 +1495,7 @@ public class DNIeCardSecureChannel {  	private byte[] rsaEncrypt(Key key, byte[] data)
  			throws NoSuchAlgorithmException, NoSuchPaddingException,
  			InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
 -
 +		
  		Cipher rsa = Cipher.getInstance("RSA/ECB/NoPadding");
  		rsa.init(Cipher.ENCRYPT_MODE, key);
  		byte[] encrypted = rsa.doFinal(data);
 @@ -1622,5 +1644,5 @@ public class DNIeCardSecureChannel {  		return (sw1 * 256) + sw2;
  	}
 -
 +	
  }
 diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java index a6056de5..113f00cb 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java @@ -276,12 +276,12 @@ public class SignatureCardFactory {              new byte[] { (byte) 0x3b, (byte) 0x7F, (byte) 0x38,                      (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6A,                      (byte) 0x44, (byte) 0x4E, (byte) 0x49, (byte) 0x65, -                    (byte) 0x20, (byte) 0x02, (byte) 0x4C, (byte) 0x34, (byte) 0x01, (byte) 0x13, (byte) 0x03, (byte) 0x90, (byte) 0x00 }, +                    (byte) 0x00, (byte) 0x02, (byte) 0x4C, (byte) 0x34, (byte) 0x01, (byte) 0x13, (byte) 0x03, (byte) 0x90, (byte) 0x00 },              // mask (ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff)              new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff,                      (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,                      (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, -                    (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }, +                    (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff },              "at.gv.egiz.smcc.DNIeCard"));      // ITCards | 
