/** * @authorSTF 424_ITS_Test_Platform * @version $URL$ * $Id$ */ package org.etsi.its.extfunc; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.logging.Logger; import org.etsi.adapter.GnssSupportFactory; import org.etsi.adapter.IGnssSupport; import org.etsi.adapter.TERFactory; import org.etsi.certificates.CertificatesIOFactory; import org.etsi.certificates.io.ICertificatesIO; import org.etsi.codec.ITciCDWrapper; import org.etsi.codec.TciCDWrapperFactory; import org.etsi.common.ByteHelper; import org.etsi.geodesic.DMS; import org.etsi.geodesic.Positioning; import org.etsi.geodesic.WGS84; import org.etsi.ttcn.tci.BooleanValue; import org.etsi.ttcn.tci.CharstringValue; import org.etsi.ttcn.tci.EnumeratedValue; import org.etsi.ttcn.tci.FloatValue; import org.etsi.ttcn.tci.IntegerValue; import org.etsi.ttcn.tci.OctetstringValue; import org.etsi.ttcn.tci.RecordOfValue; import org.etsi.ttcn.tci.RecordValue; import de.fraunhofer.sit.c2x.CryptoLib; import de.fraunhofer.sit.c2x.EcdsaP256KeyPair; /** * This class implements external ITS function * * See TTCN-3 modules LibItsGeoNetworking_Functions and LibItsCommon_Functions * */ public class ItsExternalFunctionsProvider implements IItsExternalFunctionsProvider { /** * Module version */ public static final String Version = "1.0.0.0"; /** * Unique instance of TciCDWrapper class */ private ITciCDWrapper _tcicdWrapper; /** * Constant factor used for distance computation */ private static final double earthRadius = 6378137; private static final double rbis = earthRadius * Math.PI / 180; private static final long ITS_REF_TIME = 1072915200000L; private static final String GNSS_SCENARIO_SUPPORT = "GnssScenarioSupport"; private IGnssSupport GNSS; private boolean gnssScenarioSupport; /** * Reference to the ePassport files manager */ private ICertificatesIO _certCache = CertificatesIOFactory.getInstance(); /** * Default ctor */ public ItsExternalFunctionsProvider() { //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "Constructor", String.format("version:%s", Version)); _tcicdWrapper = TciCDWrapperFactory.getTciCDInstance(); try { gnssScenarioSupport = ((BooleanValue) TERFactory.getInstance().getTaParameter(GNSS_SCENARIO_SUPPORT)).getBoolean(); } catch (Throwable th) { gnssScenarioSupport = false; } if (gnssScenarioSupport) { GNSS = GnssSupportFactory.getInstance(); } } /** * This external function gets the current time * * @return The current time in ITS format * * TTCN-3 signature: external function fx_getCurrentTime() return * TimestampIts; */ @Override public synchronized IntegerValue fx_getCurrentTime() { IntegerValue now = null; //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_getCurrentTime"); if (gnssScenarioSupport) { now = _tcicdWrapper.setInteger(GNSS.getGpsTime()); } else { String datestr="01/01/2004 00:00:00 +0000"; DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss Z"); try { // TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider.fx_getCurrentTime: " + ((java.util.Date)formatter.parse(datestr)).getTime()); now = _tcicdWrapper.setInteger( new BigInteger( 1, ByteHelper.longToByteArray(System.currentTimeMillis() - ((java.util.Date)formatter.parse(datestr)).getTime(), Long.SIZE / Byte.SIZE) ) ); } catch (ParseException e) { now = _tcicdWrapper.setInteger(0); } //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_getCurrentTime", String.format("%10d", _tcicdWrapper.getBigInteger(now))); } return now; } // End of method fx_getCurrentTime @Override public IntegerValue fx_getCurrentTimeMark() { IntegerValue now = null; //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_getCurrentTimeMark"); ZonedDateTime t = ZonedDateTime.now(ZoneOffset.UTC); now = _tcicdWrapper.setInteger(new Integer((t.getMinute() * 60 + t.getSecond()) * 10)); //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_getCurrentTimeMark", String.format("%4d", _tcicdWrapper.getBigInteger(now))); return now; } @Override public IntegerValue fx_getMinuteOfTheYear() { IntegerValue now = null; //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_getMinuteOfTheYear"); ZonedDateTime t = ZonedDateTime.now(ZoneOffset.UTC); now = _tcicdWrapper.setInteger(new Integer((t.getDayOfYear() - 1) * 24 * 60 + t.getHour() * 60 + t.getMinute())); //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_getMinuteOfTheYear", String.format("%4d", _tcicdWrapper.getBigInteger(now))); return now; } public IntegerValue fx_getDSecond() { IntegerValue now = null; //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_getDSecond"); ZonedDateTime t = ZonedDateTime.now(ZoneOffset.UTC); now = _tcicdWrapper.setInteger(new Integer(t.getSecond() + Math.round(t.getNano() / 1000))); //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_getDSecond", String.format("%4d", _tcicdWrapper.getBigInteger(now))); return now; } /** * This external function gets the current time * * @param p_latitudeA * Latitude of node A * @param p_longitudeA * Longitude of node A * @param p_latitudeB * Latitude of node B * @param p_longitudeB * Longitude of node B * @return The current time in Epoch format * * TTCN-3 signature: external function fx_computeDistance(in UInt32 * p_latitudeA, in UInt32 p_longitudeA, in UInt32 p_latitudeB, in * UInt32 p_longitudeB) return float; */ @Override public synchronized FloatValue fx_computeDistance( final IntegerValue p_latitudeA, final IntegerValue p_longitudeA, final IntegerValue p_latitudeB, final IntegerValue p_longitudeB) { // //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_computeDistance", // String.format("%d, %d, %d, %d", // p_latitudeA.getInteger(), // p_longitudeA.getInteger(), // p_latitudeB.getInteger(), // p_longitudeB.getInteger())); // Initialise the returned value FloatValue dist = _tcicdWrapper.getFloat(); double dlat = ( new Double(_tcicdWrapper.getInteger(p_latitudeB)) - new Double(_tcicdWrapper.getInteger(p_latitudeA)) ) / 10000000; double dlong = ( new Double(_tcicdWrapper.getInteger(p_longitudeB)) - new Double(_tcicdWrapper.getInteger(p_longitudeA)) ) / 10000000; long d = Math.round(Math.sqrt(Math.pow(dlat * rbis, 2) + Math.pow(dlong * rbis * Math.cos(dlat), 2))); dist.setFloat(d); return dist; } // End of method fx_computeDistance /** * External function to compute a position using a reference position, a * distance and an orientation * * @param p_iutLongPosVector * Reference position * @param p_distance * Distance to the reference position (in meter) * @param p_orientation * Direction of the computed position (0 to 359; 0 means North) * @param p_latitude * Computed position's latitude * @param p_longitude * Computed position's longitude * * TTCN-3 signature: external function * fx_computePositionUsingDistance(in LongPosVector * p_iutLongPosVector, in integer p_distance, in integer * p_orientation, out UInt32 p_latitude, out UInt32 p_longitude); */ @Override public synchronized void fx_computePositionUsingDistance( final IntegerValue p_refLatitude, final IntegerValue p_refLongitude, final FloatValue p_distance, final IntegerValue p_orientation, IntegerValue p_latitude, IntegerValue p_longitude) { // //TERFactory.getInstance().logDebug( // "ItsExternalFunctionsProvider", // "fx_computePositionUsingDistance", // String.format("%d, %d", p_distance.getInteger(), // p_orientation.getInteger())); FloatValue v_distance = _tcicdWrapper.getFloat(); v_distance.setFloat(p_distance.getFloat()); double angularD = new Double(v_distance.getFloat()) / earthRadius; double radHeading = new Double(_tcicdWrapper.getInteger(p_orientation)) * Math.PI / 180; // Convert to rad double lat1 = (new Double(_tcicdWrapper.getInteger(p_refLatitude)) / 10000000) * Math.PI / 180; double long1 = (new Double(_tcicdWrapper.getInteger(p_refLongitude)) / 10000000) * Math.PI / 180; double lat2 = Math.asin(Math.sin(lat1) * Math.cos(angularD) + Math.cos(lat1) * Math.sin(angularD) * Math.cos(radHeading)); double long2 = long1 + Math.atan2( Math.sin(radHeading) * Math.sin(angularD) * Math.cos(lat1), Math.cos(angularD) - Math.sin(lat1) * Math.sin(lat2)); // normalise to -180...+180 long2 = (long2 + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // convert to 1/10 of microdegrees Long rlat2 = Math.round(lat2 * 10000000 / Math.PI * 180); Long rlong2 = Math.round(long2 * 10000000 / Math.PI * 180); // The out parameter needs to be set on the object level _tcicdWrapper.setInteger(p_latitude, rlat2.intValue()); _tcicdWrapper.setInteger(p_longitude, rlong2.intValue()); // p_latitude = _tcicdWrapper.setInteger((int) rlat2); // p_longitude = _tcicdWrapper.setInteger((int) rlong2); } // End of method fx_computePositionUsingDistance /** * External function to compute a position using a rotation * * @param p_iutLongPosVector * Reference position * @param p_rotation * Rotation value (in degrees) * @param p_latitude * Computed position's latitude * @param p_longitude * Computed position's longitude * * TTCN-3 signature: external function * fx_computePositionFromRotation(in LongPosVector * p_iutLongPosVector, in Int32 * p_rotation, out Int32 p_latitude, out Int32 p_longitude); * @remark See http://www.movable-type.co.uk/scripts/latlong.html */ @Override public synchronized void fx_computePositionFromRotation( final IntegerValue p_refLatitude, final IntegerValue p_refLongitude, final IntegerValue p_cenLatitude, final IntegerValue p_cenLongitude, final IntegerValue p_rotation, IntegerValue p_latitude, IntegerValue p_longitude) { //TERFactory.getInstance().logDebug( // "ItsExternalFunctionsProvider", // "fx_computePositionFromRotation", // String.format("%d", p_rotation.getFloat())); // 1. Compute distance between the 2 points double lat1 = Math.toRadians((double)_tcicdWrapper.getInteger(p_cenLatitude) / 10000000.0); double long1 = Math.toRadians((double)_tcicdWrapper.getInteger(p_cenLongitude) / 10000000.0); double lat2 = Math.toRadians((double)_tcicdWrapper.getInteger(p_refLatitude) / 10000000.0); double long2 = Math.toRadians((double)_tcicdWrapper.getInteger(p_refLongitude) / 10000000.0); double dlat = lat2 - lat1; double dlong = long2 - long1; double a = Math.sin(dlat / 2) * Math.sin(dlat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dlong / 2) * Math.sin(dlong / 2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); //double d = earthRadius * c; //TERFactory.getInstance().logDebug("fx_computePositionFromRotation: Angular distance = " + c); // 2. Compute bearing double y = Math.sin(long2 - long1) * Math.cos(lat2); double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(long2 - long1); double brng = Math.atan2(y, x); //TERFactory.getInstance().logDebug("fx_computePositionFromRotation: Bearing = " + Math.toDegrees(brng)); // 3. Compute distance between the 2 points double rotation = Math.toRadians((double)_tcicdWrapper.getInteger(p_rotation) / 10.0) + brng; //TERFactory.getInstance().logDebug("fx_computePositionFromRotation = rotation: " + Math.toDegrees(rotation)); double lat = Math.asin(Math.sin(lat1) * Math.cos(c) + Math.cos(lat1) * Math.sin(c) * Math.cos(rotation)); double long_ = long1 + Math.atan2(Math.sin(rotation) * Math.sin(c)*Math.cos(lat1), Math.cos(c) - Math.sin(lat1) * Math.sin(lat)); // 4. Normalize // normalise to -180...+180 long_ = (long_ + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // The out parameter needs to be set on the object level Long rlat = Math.round(Math.toDegrees(lat) * 10000000); Long rlong = Math.round(Math.toDegrees(long_) * 10000000); _tcicdWrapper.setInteger(p_latitude, rlat.intValue()); _tcicdWrapper.setInteger(p_longitude, rlong.intValue()); //TERFactory.getInstance().logDebug("Lat = " + p_latitude.getInteger() + " - long = " + p_longitude.getInteger()); } // End of method fx_computePositionFromRotation @Override public FloatValue fx_computeRadiusFromCircularArea(FloatValue p_squareMeters) { // Initialise the returned value FloatValue radius = _tcicdWrapper.getFloat(); radius.setFloat((float) Math.sqrt(p_squareMeters.getFloat() / Math.PI)); return radius; } /** * External function to compute timestamp based on current time * * @return Unix-Epoch-Time mod 2^32 * * TTCN-3 signature: external function fx_computeGnTimestamp() * return UInt32; */ @Override public IntegerValue fx_computeGnTimestamp() { IntegerValue timestamp = _tcicdWrapper.setInteger( new BigInteger( 1, ByteHelper.longToByteArray((System.currentTimeMillis() - ITS_REF_TIME) % (long)Math.pow(2,32), Long.SIZE / Byte.SIZE) ) ); return timestamp; } /** * @desc Calculate ICMPv6 checksum on pseudo header according RFC 4443 - * Clause 2.3 * @param p_sourceAddress * Source address (128 bits), * @param p_destinationAddress * Destination address (128 bits) * @param p_payloadLength * Upper-Layer Packet Length (32 bits) * @param p_payload * Upper-Layer payload * @param p_nextHdr * Next header value (e.g. 0x3a for ICMPv6) (8bits) * @return The checksum value (16bits) * @see RFC 2460 IPv6 Specification * * TTCN-3 signature: external function fx_computeIPv6CheckSum( in * template (value) Ipv6Address p_sourceAddress, in template (value) * Ipv6Address p_destinationAddress, in template (value) integer * p_payloadLength, in template (value) octetstring p_payload, in * template (value) integer p_nextHdr ) return Oct2; * *
* Pseudo header is defined by RFC 2460 - Clause 8.1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * + + * | | * + Source Address + * | | * + + * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * + + * | | * + Destination Address + * | | * + + * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Upper-Layer Packet Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | zero | Next Header | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ **/ @Override public OctetstringValue fx_computeIPv6CheckSum( final OctetstringValue p_sourceAddress, final OctetstringValue p_destinationAddress, final IntegerValue p_payloadLength, final OctetstringValue p_payload, final IntegerValue p_nextHdr) { //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_computeIPv6CheckSum"); // Build the pseudo header according RFC 2460 - Clause 8.1 ByteArrayOutputStream pseudoheader = new ByteArrayOutputStream(); // Source address (128bits) int i = 0; for (; i < p_sourceAddress.getLength(); i++) { pseudoheader.write(p_sourceAddress.getOctet(i)); } // End of 'for' loop // Destination address (128bits) for (i = 0; i < p_destinationAddress.getLength(); i++) { pseudoheader.write(p_destinationAddress.getOctet(i)); } // End of 'for' loop try { // Upper-Layer Packet Length (32bits) pseudoheader.write(ByteHelper.intToByteArray(_tcicdWrapper.getInteger(p_payloadLength), 4)); // Checksum set to 0 (24bits) pseudoheader.write(ByteHelper.intToByteArray(0, 3)); // Next header (8bits) pseudoheader.write((byte) _tcicdWrapper.getInteger(p_nextHdr)); } catch (IOException e) { e.printStackTrace(); } // Add the payload for (i = 0; i < p_payload.getLength(); i++) { pseudoheader.write(p_payload.getOctet(i)); } // End of 'for' loop i = 0; int length = pseudoheader.size(); byte[] buffer = pseudoheader.toByteArray(); ByteHelper .dump("ItsExternalFunctionsProvider.fx_computeIPv6CheckSum: pseaudo header", buffer); long sum = 0; while (length > 0) { sum += (buffer[i++] & 0xff) << 8; if ((--length) == 0) { break; } sum += (buffer[i++] & 0xff); --length; } sum = (~((sum & 0xFFFF) + (sum >> 16))) & 0xFFFF; //TERFactory.getInstance().logDebug(String.format("ItsExternalFunctionsProvider.fx_computeIPv6CheckSum: finalSum=%d",sum)); // Set the return value OctetstringValue checksum = _tcicdWrapper.getOctetstring(); checksum.setLength(2); checksum.setOctet(0, (byte) ((byte) (sum >> 8) & 0xff)); checksum.setOctet(1, (byte) (sum & 0x00ff)); //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_computeIPv6CheckSum", checksum); // FIXME Check which method to call for logging return checksum; } @Override public OctetstringValue xf_parseIpv6Address( CharstringValue p_textIpv6Address) { byte[] hexIpv6Address = null; try { InetAddress ipv6Address = InetAddress.getByName(p_textIpv6Address .getString()); hexIpv6Address = ipv6Address.getAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } OctetstringValue result = _tcicdWrapper.getOctetstring(); result.setLength(hexIpv6Address.length); for (int i = 0; i < hexIpv6Address.length; i++) { result.setOctet(i, hexIpv6Address[i]); } return result; } /** * @desc Produces a 256-bit (32-byte) hash value * @param p_toBeHashedData Data to be used to calculate the hash value * @return The hash value */ public OctetstringValue fx_hashWithSha256(final OctetstringValue p_toBeHashedData) { //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_hashWithSha256"); byte[] toBeHashedData = new byte[p_toBeHashedData.getLength()]; for (int i = 0; i < toBeHashedData.length; i++) { toBeHashedData[i] = (byte) p_toBeHashedData.getOctet(i); } // End 'for' statement byte[] hash = CryptoLib.hashWithSha256(toBeHashedData); OctetstringValue result = _tcicdWrapper.getOctetstring(); result.setLength(hash.length); for (int i = 0; i < hash.length; i++) { result.setOctet(i, hash[i]); } // End 'for' statement return result; } /** * @desc Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signaturee * @param p_toBeSignedData The data to be signed * @param p_privateKey The private key * @return The signature value */ public OctetstringValue fx_signWithEcdsaNistp256WithSha256(final OctetstringValue p_toBeSignedData, final OctetstringValue/*IntegerValue*/ p_privateKey) { //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_signWithEcdsaNistp256WithSha256"); byte[] toBeSignedData = new byte[p_toBeSignedData.getLength()]; for (int i = 0; i < toBeSignedData.length; i++) { toBeSignedData[i] = (byte) p_toBeSignedData.getOctet(i); } // End 'for' statement byte[] privateKey = new byte[p_privateKey.getLength()]; for (int i = 0; i < privateKey.length; i++) { privateKey[i] = (byte) p_privateKey.getOctet(i); } // End 'for' statement byte[] signed; try { // TERFactory.getInstance().logDebug("fx_signWithEcdsaNistp256WithSha256: toBeSignedData=" + ByteHelper.byteArrayToString(toBeSignedData) + " - " + toBeSignedData.length); // TERFactory.getInstance().logDebug("fx_signWithEcdsaNistp256WithSha256: ts103097SignatureEncodedAsByteArray=" + new BigInteger(privateKey)); signed = CryptoLib.signWithEcdsaNistp256WithSha256(toBeSignedData, new BigInteger(privateKey)); } catch (Exception e) { e.printStackTrace(); signed = new byte[] {}; } OctetstringValue result = _tcicdWrapper.getOctetstring(); result.setLength(signed.length); for (int i = 0; i < signed.length; i++) { result.setOctet(i, signed[i]); } // End 'for' statement return result; } /** * @desc Verify the signature of the specified data * @param p_toBeVerifiedData The data to be verified * @param p_signature The signature * @param p_ecdsaNistp256PublicKeyX The public key (x coordinate) * @param p_ecdsaNistp256PublicKeyY The public key (y coordinate) * @return true on success, false otherwise */ public BooleanValue fx_verifyWithEcdsaNistp256WithSha256(final OctetstringValue p_toBeVerifiedData, final OctetstringValue p_signature, final OctetstringValue p_ecdsaNistp256PublicKeyX, final OctetstringValue p_ecdsaNistp256PublicKeyY) { //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_verifyWithEcdsaNistp256WithSha256"); BooleanValue result = _tcicdWrapper.getBoolean(); result.setBoolean(false); byte[] toBeVerifiedData = new byte[p_toBeVerifiedData.getLength()]; for (int i = 0; i < toBeVerifiedData.length; i++) { toBeVerifiedData[i] = (byte) p_toBeVerifiedData.getOctet(i); } // End 'for' statement byte[] ts103097SignatureEncodedAsByteArray = new byte[p_signature.getLength()]; for (int i = 0; i < ts103097SignatureEncodedAsByteArray.length; i++) { ts103097SignatureEncodedAsByteArray[i] = (byte) p_signature.getOctet(i); } // End 'for' statement byte[] ecdsaNistp256PublicKeyX = new byte[p_ecdsaNistp256PublicKeyX.getLength()]; for (int i = 0; i < ecdsaNistp256PublicKeyX.length; i++) { ecdsaNistp256PublicKeyX[i] = (byte) p_ecdsaNistp256PublicKeyX.getOctet(i); } // End 'for' statement byte[] ecdsaNistp256PublicKeyY = new byte[p_ecdsaNistp256PublicKeyY.getLength()]; for (int i = 0; i < ecdsaNistp256PublicKeyY.length; i++) { ecdsaNistp256PublicKeyY[i] = (byte) p_ecdsaNistp256PublicKeyY.getOctet(i); } // End 'for' statement try { // TERFactory.getInstance().logDebug("fx_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData=" + ByteHelper.byteArrayToString(toBeVerifiedData) + " - " + toBeVerifiedData.length); // TERFactory.getInstance().logDebug("fx_verifyWithEcdsaNistp256WithSha256: ts103097SignatureEncodedAsByteArray=" + ByteHelper.byteArrayToString(ts103097SignatureEncodedAsByteArray)); // TERFactory.getInstance().logDebug("fx_verifyWithEcdsaNistp256WithSha256: ecdsaNistp256PublicKeyX=" + ByteHelper.byteArrayToString(ecdsaNistp256PublicKeyX)); // TERFactory.getInstance().logDebug("fx_verifyWithEcdsaNistp256WithSha256: ecdsaNistp256PublicKeyY=" + ByteHelper.byteArrayToString(ecdsaNistp256PublicKeyY)); boolean ret = CryptoLib.verifyWithEcdsaNistp256WithSha256(toBeVerifiedData, ts103097SignatureEncodedAsByteArray, ecdsaNistp256PublicKeyX, ecdsaNistp256PublicKeyY); result.setBoolean(ret); } catch (Exception e) { e.printStackTrace(); } //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_verifyWithEcdsaNistp256WithSha256"); return result; } /** * @desc Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm * @param p_privateKey The new private key value * @param p_publicKeyX The new public key value (x coordinate) * @param p_publicKeyX The new public key value (y coordinate) * @return true on success, false otherwise */ public BooleanValue fx_generateKeyPair(OctetstringValue/*IntegerValue*/ p_privateKey, OctetstringValue p_publicKeyX, OctetstringValue p_publicKeyY) { //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_generateKeyPair"); BooleanValue result = _tcicdWrapper.getBoolean(); result.setBoolean(true); EcdsaP256KeyPair ecdsaP256KeyPair = CryptoLib.generateKeyPair(); byte[] ref = ecdsaP256KeyPair.getPrivateKey().toByteArray(); p_privateKey.setLength(ref.length); for (int i = 0; i < p_privateKey.getLength(); i++) { p_privateKey.setOctet(i, ref[i]); } // End 'for' statement ref = ecdsaP256KeyPair.getPublicKeyX(); p_publicKeyX.setLength(ref.length); for (int i = 0; i < ref.length; i++) { p_publicKeyX.setOctet(i, ref[i]); } // End 'for' statement ref = ecdsaP256KeyPair.getPublicKeyY(); p_publicKeyY.setLength(ref.length); for (int i = 0; i < ref.length; i++) { p_publicKeyY.setOctet(i, ref[i]); } // End 'for' statement //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_generateKeyPair"); return result; } /** * @desc Check that given polygon doesn't have neither self-intersections nor holes. * @param p_region Polygonal Region * @return true on success, false otherwise */ public BooleanValue fx_isValidPolygonalRegion(final RecordOfValue p_region) { //TERFactory.getInstance().logDebug("ItsExternalFunctionsProvider", "fx_isValidPolygonalRegion"); // Setup arguments ArrayList