package de.persosim.simulator.protocols; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import java.security.GeneralSecurityException; import java.security.InvalidAlgorithmParameterException; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.SecureRandom; import java.security.interfaces.ECPublicKey; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import org.junit.Before; import org.junit.Test; import de.persosim.simulator.cardobjects.DomainParameterSetCardObject; import de.persosim.simulator.cardobjects.DomainParameterSetIdentifier; import de.persosim.simulator.cardobjects.MasterFile; import de.persosim.simulator.cardobjects.OidIdentifier; import de.persosim.simulator.crypto.DomainParameterSetEcdh; import de.persosim.simulator.crypto.StandardizedDomainParameters; import de.persosim.simulator.crypto.certificates.CvPublicKey; import de.persosim.simulator.exception.NotParseableException; import de.persosim.simulator.protocols.pace.Pace; import de.persosim.simulator.protocols.pace.PaceOid; import de.persosim.simulator.test.PersoSimTestCase; import de.persosim.simulator.tlv.ConstructedTlvDataObject; import de.persosim.simulator.tlv.TlvDataObjectContainer; import de.persosim.simulator.utils.HexString; import mockit.Capturing; import mockit.Expectations; import mockit.Mocked; import mockit.NonStrictExpectations; public class Tr03110UtilsTest extends PersoSimTestCase { @Mocked MasterFile mf; Oid oid1, oid2; OidIdentifier oidIdentifier1, oidIdentifier2; DomainParameterSetCardObject domainParameters12, domainParameters13; DomainParameterSetIdentifier domainparameterSetIdentifier12, domainparameterSetIdentifier13; @Before public void setUp() throws Exception{ // define domain parameters oid1 = Pace.OID_id_PACE_ECDH_GM_AES_CBC_CMAC_256; oidIdentifier1 = new OidIdentifier(oid1); oid2 = Pace.OID_id_PACE_ECDH_GM_AES_CBC_CMAC_128; oidIdentifier2 = new OidIdentifier(oid2); domainparameterSetIdentifier12 = new DomainParameterSetIdentifier(12); domainParameters12 = new DomainParameterSetCardObject(StandardizedDomainParameters.getDomainParameterSetById(12), domainparameterSetIdentifier12); domainParameters12.addOidIdentifier(oidIdentifier1); domainparameterSetIdentifier13 = new DomainParameterSetIdentifier(13); domainParameters13 = new DomainParameterSetCardObject(StandardizedDomainParameters.getDomainParameterSetById(13), domainparameterSetIdentifier13); domainParameters13.addOidIdentifier(oidIdentifier2); } /** * Positive test: build authentication token with EC public key. */ @Test public void testBuildAuthenticationTokenInputEcPublicKey() { Oid oid = new PaceOid(Pace.id_PACE_ECDH_GM_AES_CBC_CMAC_256); // arbitrary OID with matching key agreement and key length DomainParameterSetEcdh domainParametersEcdh = (DomainParameterSetEcdh) StandardizedDomainParameters.getDomainParameterSetById(13); byte[] ecdhPublicKeyDataPicc = HexString.toByteArray("04A44EBE5451DF7AADB01E459B8C928A87746A57927C8C28A6775C97A7E1FE8D9A46FF4A1CC7E4D1389AEA19758E4F75C28C598FD734AEBEB135337CF95BE12E94"); ECPublicKey ecdhPublicKeyPicc = domainParametersEcdh.reconstructPublicKey(ecdhPublicKeyDataPicc); byte[] tokenExpected = HexString.toByteArray("7F494F060A04007F00070202040204864104A44EBE5451DF7AADB01E459B8C928A87746A57927C8C28A6775C97A7E1FE8D9A46FF4A1CC7E4D1389AEA19758E4F75C28C598FD734AEBEB135337CF95BE12E94"); TlvDataObjectContainer tokenReceived = Tr03110Utils.buildAuthenticationTokenInput(ecdhPublicKeyPicc, domainParametersEcdh, oid); byte[] tokenReceivedPlain = tokenReceived.toByteArray(); assertArrayEquals("token mismatch", tokenExpected, tokenReceivedPlain); } /** * Positive test: check parsing of a valid date encoding for input length 6. * @throws NotParseableException */ @Test public void testParseDate_inputLength6() throws NotParseableException { byte[] date = HexString.toByteArray("010001010202"); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.MILLISECOND, 0); calendar.set(2010, Calendar.NOVEMBER, 22, 0, 0, 0); calendar.setTimeZone(TimeZone.getTimeZone("GMT")); Date expectedDate = calendar.getTime(); Date receivedDate = Tr03110Utils.parseDate(date); assertEquals(expectedDate, receivedDate); } /** * Negative test: check parsing of a date encoding of illegal length. * @throws NotParseableException */ @Test(expected = NotParseableException.class) public void testParseDate_illegalLength() throws NotParseableException { byte[] date = HexString.toByteArray("0100010102"); Tr03110Utils.parseDate(date); } /** * Negative test: check parsing of a date encoding encoding non-numeric characters. * @throws NotParseableException */ @Test(expected = NotParseableException.class) public void testParseDate_nonNumericCharacters() throws NotParseableException { byte[] date = HexString.toByteArray("01000101020A"); Tr03110Utils.parseDate(date); } /** * Positive test: Convert the Date 01.01.2070 to its BCD representation */ @Test public void testEncodeDate_singleCharacters() { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.MILLISECOND, 0); calendar.set(2070, Calendar.JANUARY, 1, 0, 0, 0); Date date = calendar.getTime(); byte [] expected = HexString.toByteArray("070000010001"); assertArrayEquals(expected, Tr03110Utils.encodeDate(date)); } /** * Positive test: Convert the Date 23.12.2078 to its BCD representation */ @Test public void testEncodeDate_doubleCharacters() { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.MILLISECOND, 0); calendar.set(2078, Calendar.DECEMBER, 23, 0, 0, 0); Date date = calendar.getTime(); byte [] expected = HexString.toByteArray("070801020203"); assertArrayEquals(expected, Tr03110Utils.encodeDate(date)); } /** * This tests if the * {@link Tr03110Utils#parseCertificatePublicKey(de.persosim.simulator.tlv.ConstructedTlvDataObject, PublicKey)} * method correctly handles exceptions thrown by providers. * * @param provider * @throws GeneralSecurityException */ @Test public void testParseCertificatePublicKeyExceptionInProvider( @Capturing final Tr03110UtilsProvider provider) throws GeneralSecurityException{ // prepare the mock new NonStrictExpectations() { { provider.parseCvPublicKey(null); result = new GeneralSecurityException(); } }; assertNull(Tr03110Utils.parseCvPublicKey(null)); } /** * This test checks if a key object returned by a provider is delivered by * {@link Tr03110Utils#parseCertificatePublicKey(de.persosim.simulator.tlv.ConstructedTlvDataObject, PublicKey)} * * @param provider * @throws GeneralSecurityException */ @Test public void testParseCertificatePublicKeyResultFound( @Capturing final Tr03110UtilsProvider provider) throws GeneralSecurityException{ // prepare the mock final CvPublicKey key = new CvPublicKey(null, null) { private static final long serialVersionUID = 1L; @Override public ConstructedTlvDataObject toTlvDataObject(boolean includeConditionalObjects) {return null;} @Override public boolean isComplete() {return false;} @Override public boolean updateKey(PublicKey publicKey) {return false;} @Override public KeyPairGenerator getKeyPairGenerator(SecureRandom secRandom) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { return null; } @Override public boolean matchesCoreMaterial(CvPublicKey publicKey) { return false; }}; new Expectations() { { provider.parseCvPublicKey(null); result = key; } }; assertSame(key, Tr03110Utils.parseCvPublicKey(null)); } }