From 4a7a5d775cdfb13b880dcda28c11f7cea35eb767 Mon Sep 17 00:00:00 2001 From: berge Date: Tue, 18 Nov 2014 09:18:17 +0000 Subject: [PATCH] Merged branches/Security/javasrc (r1425-1803) to trunk. This completes cleaning operation of r1821 by re-inserting non-STF455 specific changes in trunk --- .../etsi/its/adapter/IManagementLayers.java | 143 ++- .../org/etsi/its/adapter/Management.java | 521 ++++++---- .../org/etsi/its/adapter/PcapMultiplexer.java | 15 +- .../org/etsi/its/adapter/TestAdapter.java | 544 +++++------ .../org/etsi/its/adapter/TlsHelper.java | 77 ++ .../org/etsi/its/adapter/layers/GnLayer.java | 900 +++++++++++------- .../etsi/its/adapter/layers/LayerFactory.java | 73 +- .../its/adapter/ports/AdapterControlPort.java | 216 +++-- .../org/etsi/its/adapter/ports/GnPort.java | 555 ++++++++--- .../adapter/ports/ProtocolPortFactory.java | 87 +- .../certificates/CertificatesIOFactory.java | 32 + .../org/etsi/certificates/Helpers.java | 121 +++ .../etsi/certificates/io/CertificatesIO.java | 251 +++++ .../etsi/certificates/io/ICertificatesIO.java | 48 + .../codec/org/etsi/codec/ITciCDWrapper.java | 154 ++- .../org/etsi/ttcn/codec/CodecBuffer.java | 4 +- .../org/etsi/ttcn/codec/CodecFactory.java | 11 +- javasrc/codec/org/etsi/ttcn/codec/ICodec.java | 7 +- .../codec/org/etsi/ttcn/codec/MainCodec.java | 50 +- .../etsi/ttcn/codec/generic/Bitstring.java | 5 +- .../etsi/ttcn/codec/generic/Charstring.java | 5 +- .../etsi/ttcn/codec/generic/Enumerated.java | 2 + .../org/etsi/ttcn/codec/generic/Float.java | 41 + .../org/etsi/ttcn/codec/generic/Integer.java | 45 +- .../etsi/ttcn/codec/generic/Octetstring.java | 6 + .../org/etsi/ttcn/codec/generic/RecordOf.java | 2 + .../org/etsi/ttcn/codec/generic/Union.java | 35 +- .../org/etsi/ttcn/codec/ipv6/Ipv6ExtHdr.java | 3 +- .../ttcn/codec/its/adapter/AcGnPrimitive.java | 12 + .../etsi/ttcn/codec/its/btp/BtpHeader.java | 7 + .../etsi/ttcn/codec/its/btp/BtpPacket.java | 32 + .../ttcn/codec/its/btp/DecodedBtpPayload.java | 25 + .../org/etsi/ttcn/codec/its/btp/Payload.java | 8 +- .../org/etsi/ttcn/codec/its/btp/Plugin.java | 5 +- .../etsi/ttcn/codec/its/btp/UtBtpEvent.java | 18 + .../codec/its/geonetworking/BasicHeader.java | 22 + .../codec/its/geonetworking/CommonHeader.java | 29 +- .../codec/its/geonetworking/GN_Address.java | 38 + .../geonetworking/GeoNetworkingPacket.java | 116 ++- .../its/geonetworking/GeoNetworkingPdu.java | 34 + .../codec/its/geonetworking/GnIndReq.java | 25 +- .../its/geonetworking/GnNonSecuredPacket.java | 45 +- .../codec/its/geonetworking/HeaderTST.java | 1 + .../its/geonetworking/LongPosVector.java | 35 + .../ttcn/codec/its/geonetworking/Payload.java | 5 +- .../ttcn/codec/its/geonetworking/Plugin.java | 5 +- .../codec/its/geonetworking/TrafficClass.java | 38 + .../codec/its/security/AcEnableSecurity.java | 41 + .../etsi/ttcn/codec/its/security/AesCcm.java | 49 + .../ttcn/codec/its/security/Certificate.java | 35 + .../its/security/CertificateWithAlgo.java | 35 + .../codec/its/security/CircularRegion.java | 17 + .../ttcn/codec/its/security/Duration.java | 40 + .../ttcn/codec/its/security/EccPoint.java | 96 ++ .../codec/its/security/EcdsaSignature.java | 69 ++ .../codec/its/security/EciesEncryptedKey.java | 62 ++ .../its/security/EncryptionParameters.java | 56 ++ .../EncryptionParametersContainer.java | 34 + .../codec/its/security/GeographicRegion.java | 71 ++ .../security/GeographicRegionContainer.java | 30 + .../codec/its/security/GnSecurityInd.java | 35 + .../ttcn/codec/its/security/HashedId3.java | 29 + .../ttcn/codec/its/security/HashedId8.java | 22 + .../ttcn/codec/its/security/HeaderField.java | 92 ++ .../its/security/HeaderFieldContainer.java | 39 + .../codec/its/security/IdentifiedRegion.java | 29 + .../etsi/ttcn/codec/its/security/IntX.java | 86 ++ .../ttcn/codec/its/security/ItsAidSsp.java | 56 ++ .../etsi/ttcn/codec/its/security/Plugin.java | 126 +++ .../ttcn/codec/its/security/PublicKey.java | 49 + .../codec/its/security/RecipientInfo.java | 48 + .../its/security/RecipientInfoContainer.java | 30 + .../ttcn/codec/its/security/RecordOf.java | 60 ++ .../codec/its/security/RegionDictionary.java | 22 + .../ttcn/codec/its/security/SecPayload.java | 56 ++ .../codec/its/security/SecuredMessage.java | 24 + .../security/ServiceSpecificPermissions.java | 59 ++ .../ttcn/codec/its/security/Signature.java | 46 + .../ttcn/codec/its/security/SignerInfo.java | 77 ++ .../its/security/SignerInfoContainer.java | 31 + .../etsi/ttcn/codec/its/security/SspDENM.java | 39 + .../codec/its/security/SubjectAssurance.java | 41 + .../codec/its/security/SubjectAttribute.java | 73 ++ .../security/SubjectAttributeContainer.java | 29 + .../ttcn/codec/its/security/SubjectInfo.java | 54 ++ .../codec/its/security/ThreeDLocation.java | 34 + .../etsi/ttcn/codec/its/security/Time32.java | 24 + .../etsi/ttcn/codec/its/security/Time64.java | 23 + .../security/Time64WithStandardDeviation.java | 25 + .../ttcn/codec/its/security/TlsHelper.java | 74 ++ .../its/security/ToBeSignedCertificate.java | 44 + .../ttcn/codec/its/security/TrailerField.java | 59 ++ .../its/security/TrailerFieldContainer.java | 30 + .../ttcn/codec/its/security/TwoDLocation.java | 23 + .../its/security/ValidityRestriction.java | 66 ++ .../ValidityRestrictionContainer.java | 29 + .../its/uppertester/UtDenmTermination.java | 16 +- .../ttcn/codec/its/uppertester/UtPduId.java | 7 + .../etsi/ttcn/codec/lowpan/IphcHeader.java | 3 +- .../org/etsi/ttcn/common/ByteHelper.java | 22 +- .../common/org/etsi/common/ByteHelper.java | 324 ++++--- javasrc/common/org/etsi/common/KPM.java | 61 ++ .../IItsExternalFunctionsProvider.java | 135 ++- .../extfunc/ItsExternalFunctionsProvider.java | 526 +++++++++- .../org/etsi/geodesic/CountriesAreas.java | 462 +++++++++ javasrc/geodesic/org/etsi/geodesic/DMS.java | 55 ++ .../org/etsi/geodesic/ICountriesAreas.java | 27 + .../org/etsi/geodesic/IPositioning.java | 71 ++ .../org/etsi/geodesic/Positioning.java | 173 ++++ javasrc/geodesic/org/etsi/geodesic/WGS84.java | 112 +++ .../etsi/its/tool/elvior/BuiltInCodec.java | 161 ++++ .../its/tool/elvior/GetValueStructure.java | 121 +++ .../its/tool/elvior/Its_CodecProvider.java | 66 +- .../its/tool/elvior/LibItsCALMllsap_asn1.java | 31 + .../its/tool/elvior/LibItsCALMmsap_asn1.java | 41 + .../etsi/its/tool/elvior/LibItsCam_asn1.java | 19 +- .../etsi/its/tool/elvior/LibItsDenm_asn1.java | 16 + .../etsi/its/tool/elvior/LibItsFntp_asn1.java | 33 + .../etsi/its/tool/elvior/LibItsFsap_asn1.java | 13 + .../etsi/its/tool/elvior/LibItsIicp_asn1.java | 33 + .../org/etsi/its/tool/elvior/LibIts_asn1.java | 27 +- .../etsi/its/tool/elvior/PluginAdapter.java | 755 ++++++++++++++- .../etsi/its/tool/elvior/res/codec.properties | 2 +- .../etsi/its/tool/elvior/res/ta.properties | 35 +- .../ExternalFunctionsPluginProvider.java | 280 ++++-- .../tool/testingtech/Its_CodecProvider.java | 50 +- .../org/etsi/tool/elvior/TciCDWrapper.java | 92 +- .../etsi/tool/testingtech/TciCDWrapper.java | 178 ++-- 128 files changed, 8922 insertions(+), 1796 deletions(-) create mode 100644 javasrc/adapter/org/etsi/its/adapter/TlsHelper.java create mode 100644 javasrc/certificatesio/org/etsi/certificates/CertificatesIOFactory.java create mode 100644 javasrc/certificatesio/org/etsi/certificates/Helpers.java create mode 100644 javasrc/certificatesio/org/etsi/certificates/io/CertificatesIO.java create mode 100644 javasrc/certificatesio/org/etsi/certificates/io/ICertificatesIO.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/btp/BtpPacket.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/btp/DecodedBtpPayload.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/btp/UtBtpEvent.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GN_Address.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GeoNetworkingPdu.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/LongPosVector.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/TrafficClass.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/AcEnableSecurity.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/AesCcm.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/Certificate.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/CertificateWithAlgo.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/CircularRegion.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/Duration.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/EccPoint.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/EcdsaSignature.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/EciesEncryptedKey.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/EncryptionParameters.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/EncryptionParametersContainer.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/GeographicRegion.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/GeographicRegionContainer.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/GnSecurityInd.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/HashedId3.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/HashedId8.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/HeaderField.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/HeaderFieldContainer.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/IdentifiedRegion.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/IntX.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/ItsAidSsp.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/Plugin.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/PublicKey.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/RecipientInfo.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/RecipientInfoContainer.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/RecordOf.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/RegionDictionary.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/SecPayload.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/SecuredMessage.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/ServiceSpecificPermissions.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/Signature.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/SignerInfo.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/SignerInfoContainer.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/SspDENM.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectAssurance.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectAttribute.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectAttributeContainer.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectInfo.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/ThreeDLocation.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/Time32.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/Time64.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/Time64WithStandardDeviation.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/TlsHelper.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/ToBeSignedCertificate.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/TrailerField.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/TrailerFieldContainer.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/TwoDLocation.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/ValidityRestriction.java create mode 100644 javasrc/codec/org/etsi/ttcn/codec/its/security/ValidityRestrictionContainer.java create mode 100644 javasrc/common/org/etsi/common/KPM.java create mode 100644 javasrc/geodesic/org/etsi/geodesic/CountriesAreas.java create mode 100644 javasrc/geodesic/org/etsi/geodesic/DMS.java create mode 100644 javasrc/geodesic/org/etsi/geodesic/ICountriesAreas.java create mode 100644 javasrc/geodesic/org/etsi/geodesic/IPositioning.java create mode 100644 javasrc/geodesic/org/etsi/geodesic/Positioning.java create mode 100644 javasrc/geodesic/org/etsi/geodesic/WGS84.java create mode 100644 javasrc/tool/org/etsi/its/tool/elvior/BuiltInCodec.java create mode 100644 javasrc/tool/org/etsi/its/tool/elvior/GetValueStructure.java create mode 100644 javasrc/tool/org/etsi/its/tool/elvior/LibItsCALMllsap_asn1.java create mode 100644 javasrc/tool/org/etsi/its/tool/elvior/LibItsCALMmsap_asn1.java create mode 100644 javasrc/tool/org/etsi/its/tool/elvior/LibItsFntp_asn1.java create mode 100644 javasrc/tool/org/etsi/its/tool/elvior/LibItsFsap_asn1.java create mode 100644 javasrc/tool/org/etsi/its/tool/elvior/LibItsIicp_asn1.java diff --git a/javasrc/adapter/org/etsi/its/adapter/IManagementLayers.java b/javasrc/adapter/org/etsi/its/adapter/IManagementLayers.java index 817c1004b..c5697ba1a 100644 --- a/javasrc/adapter/org/etsi/its/adapter/IManagementLayers.java +++ b/javasrc/adapter/org/etsi/its/adapter/IManagementLayers.java @@ -9,6 +9,8 @@ package org.etsi.its.adapter; +import java.math.BigInteger; + import org.etsi.its.adapter.ports.GnPort; /** @@ -16,59 +18,108 @@ import org.etsi.its.adapter.ports.GnPort; */ public interface IManagementLayers { - /** - * Gets the GeoNetworking beacon header to be sent by Test Adapter for the current component - * @return Beacon header, or null if no Beacon shall be sent - */ - public byte[] getGnBeacon(); - - /** - * Registers a GN port - */ - public void registerGnPort(GnPort gnPort); + /** + * Gets the GeoNetworking beacon header to be sent by Test Adapter for the current component + * @return Beacon header, or null if no Beacon shall be sent + */ + public byte[] getGnBeacon(); + + /** + * Registers a GN port + */ + public void registerGnPort(GnPort gnPort); - /** - * Gets the GeoNetworking beaconing interval - * @return GeoNetworking beaconing interval in ms - */ - public int getGnBeaconInterval(); + /** + * Gets the GeoNetworking beaconing interval + * @return GeoNetworking beaconing interval in ms + */ + public int getGnBeaconInterval(); - /** - * Gets the GeoNetworking beacon header acting as filter for enqueueing Beacons received from neighbours - * @return Beacon header, or null if no Beacon shall be enqueued - */ - public byte[] getGnEnqueueBeacon(); - - /** - * Inserts or updates a neighbour position vector in Test Adapter internal tables - * @param mid Mid part of the neighbour's GN_Address - * @param timestamp Timestamp of the carrying message - * @param lpv Long position vector of the neighbour - */ - public void gnUpdateLocTable(byte[] mid, long timestamp, byte[] lpv); + /** + * Gets the GeoNetworking beacon header acting as filter for enqueueing Beacons received from neighbours + * @return Beacon header, or null if no Beacon shall be enqueued + */ + public byte[] getGnEnqueueBeacon(); + + /** + * Inserts or updates a neighbour position vector in Test Adapter internal tables + * @param mid Mid part of the neighbour's GN_Address + * @param timestamp Timestamp of the carrying message + * @param lpv Long position vector of the neighbour + */ + public void gnUpdateLocTable(byte[] mid, long timestamp, byte[] lpv); - /** + /** * Sets the link layer address of this component * param linkLayerAddress Link-layer address (6 bytes) */ public void setLinkLayerAddress(byte[] linkLayerAddress); - - /** - * Gets the link layer address of this component - * @return Link-layer address (6 bytes) - */ - public byte[] getLinkLayerAddress(); + + /** + * Gets the link layer address of this component + * @return Link-layer address (6 bytes) + */ + public byte[] getLinkLayerAddress(); + + /** + * Gets the latitude of this component + * @return Latitude + */ + public byte[] getLatitude(); + + /** + * Gets the Longitude of this component + * @return Longitude + */ + public byte[] getLongitude(); + + /** + * Enable the secured mode + * @param securityData data required to execute the signing process on beacons + */ + public void setSecuredMode(final byte[] securityData); - /** - * Gets the latitude of this component - * @return Latitude - */ - public byte[] getLatitude(); + /** + * Disable the secured mode + */ + public void unsetSecuredMode(); + + /** + * Gets the secured mode status + * @return true if secured mode is set, false otherwise + */ + public boolean isSecuredModeSet(); + + /** + * Gets the private key for signing process + * @return The private key + */ + public BigInteger getSigningPrivateKey(); - /** - * Gets the Longitude of this component - * @return Longitude - */ - public byte[] getLongitude(); - + /** + * Gets the public key X for signing check + * @return The public key X + */ + public byte[] getSigningPublicKeyX(); + + /** + * Gets the public key Y for signing check + * @return The public key Y + */ + public byte[] getSigningPublicKeyY(); + + /** + * Gets the AT certificate value + * @return The AT certificate value + * @remark It shall not be used when secured mode is set by the test execution + */ + byte[] getAtCertificate(); + + /** + * Gets the Hashed8 value from the AT certificate + * @return The Hashed8 value + * @remark It shall not be used when secured mode is set by the test execution + */ + byte[] getAtCertificateDigest(); + } diff --git a/javasrc/adapter/org/etsi/its/adapter/Management.java b/javasrc/adapter/org/etsi/its/adapter/Management.java index 021d88f5b..da6d338b2 100644 --- a/javasrc/adapter/org/etsi/its/adapter/Management.java +++ b/javasrc/adapter/org/etsi/its/adapter/Management.java @@ -10,12 +10,16 @@ package org.etsi.its.adapter; +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.etsi.adapter.TERFactory; +import org.etsi.certificates.CertificatesIOFactory; +import org.etsi.certificates.io.ICertificatesIO; import org.etsi.common.ByteHelper; import org.etsi.common.ITuple; import org.etsi.common.Tuple; @@ -31,12 +35,12 @@ public class Management implements IManagementTA, IManagementLayers { /** * Instances of Management */ - private static final ConcurrentMap instances = new ConcurrentHashMap(); - - /** - * GeoNetworking beaconning interval - */ - private static final int GN_BEACON_INTERVAL = Integer.decode(((CharstringValue)TERFactory.getInstance().getTaParameter("TsBeaconInterval")).getString()); + private static final ConcurrentMap instances = new ConcurrentHashMap(); + + /** + * GeoNetworking beaconning interval + */ + private static final int GN_BEACON_INTERVAL = Integer.decode(((CharstringValue)TERFactory.getInstance().getTaParameter("TsBeaconInterval")).getString()); /** * Maximum time for getting Long position vector (in seconds) @@ -57,172 +61,229 @@ public class Management implements IManagementTA, IManagementLayers { * Test system longitude */ private static final int longitude = Integer.decode(((CharstringValue)TERFactory.getInstance().getTaParameter("TsLongitude")).getString()); - - /** - * Link-layer address of Component - */ - private byte[] linkLayerAddress = null; + + /** + * Secured mode status + */ + private static final String TsSecuredMode = ((CharstringValue)TERFactory.getInstance().getTaParameter("TsSecuredMode")).getString(); + + /** + * Secured root path to access certificates & private keys + */ + private static final String TsSecuredRootPath = ((CharstringValue)TERFactory.getInstance().getTaParameter("TsSecuredRootPath")).getString(); + + /** + * Secured configuration identifier + */ + private static final String TsSecuredConfiId = ((CharstringValue)TERFactory.getInstance().getTaParameter("TsSecuredConfiId")).getString(); + + /** + * Link-layer address of Component + */ + private byte[] linkLayerAddress = null; - /** - * Registered GN Port - */ - private GnPort gnPort = null; - - /** + /** + * Registered GN Port + */ + private GnPort gnPort = null; + + /** + * Set to true is secured mode is set + */ + private boolean securedMode = false; + + /** + * The certificate identifier to used + */ + private String certificateId = "TA_CERT_A"; + + /** + * The AT certificate + */ + private byte[] atCertificate = null; + + /** + * The certificate digest to used + */ + private byte[] atCertificateDigest = null; + + /** + * The private signing key to used + */ + private byte[] signingPrivateKey = null; + + /** + * The public signing key X to used + */ + private byte[] signingPublicKeyX = null; + + /** + * The public signing key Y to used + */ + private byte[] signingPublicKeyY = null; +// private byte[] toBeSignedDataDigest = null; +// private byte[] toBeSignedDataCertificate = null; + + /** * Private constructor (Multiton pattern) */ - private Management() { - //empty - - // FIXME: For debug only: - byte[] mid = new byte[] {(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x00}; - byte[] lpv = new byte[] {(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + private Management() { + + // Check for secured mode settings in TestAdapter configuration file + if (TsSecuredMode.equals("true")) { + setupSecuredMode(); + } + + // For debug only: + byte[] mid = new byte[] {(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00}; + byte[] lpv = new byte[] {(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00}; - gnUpdateLocTable(mid, 0, lpv); - } + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00}; + gnUpdateLocTable(mid, 0, lpv); + } - /** + /** * Gets the Management instance associated to a component * @param key Component name * @return Management instance */ - public static Management getInstance(String key) { - if (instances.get(key) == null){ - // Lazily create instance and try to add it to the map - Management instance = new Management(); - instances.putIfAbsent(key, instance); - } - return instances.get(key); - } + public static Management getInstance(String key) { + if (instances.get(key) == null){ + // Lazily create instance and try to add it to the map + Management instance = new Management(); + instances.putIfAbsent(key, instance); + } + return instances.get(key); + } - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementTA#startBeaconing(byte[]) - */ - @Override - public void startBeaconing(byte[] beaconHeader) { - this.beaconHeader = beaconHeader; - if(gnPort != null) { - gnPort.startBeaconning(); - } - } - - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementTA#stopBeaconing() - */ - @Override - public void stopBeaconing() { - this.beaconHeader = null; - if(gnPort != null) { + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementTA#startBeaconing(byte[]) + */ + @Override + public void startBeaconing(byte[] beaconHeader) { + this.beaconHeader = beaconHeader; + if(gnPort != null) { + gnPort.startBeaconning(); + } + } + + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementTA#stopBeaconing() + */ + @Override + public void stopBeaconing() { + this.beaconHeader = null; + if(gnPort != null) { gnPort.stopBeaconning(); } - } - - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementTA#startEnqueueingBeacons(byte[]) - */ - @Override - public void startEnqueueingBeacons(byte[] beaconHeader) { - this.enqueueBeacon = beaconHeader; - } - - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementTA#stopEnqueueingBeacons() - */ - @Override - public void stopEnqueueingBeacons() { - this.enqueueBeacon = null; - } - - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementTA#startMultipleBeaconing(byte[], int) - */ - @Override - public void startMultipleBeaconing(byte[] beaconHeader, int nbNeighbours) { - /* TODO: Multiple beacons */ - } - - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementTA#stopMultipleBeaconing() - */ - @Override - public void stopMultipleBeaconing() { - /* TODO: Multiple beacons */ - } + } + + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementTA#startEnqueueingBeacons(byte[]) + */ + @Override + public void startEnqueueingBeacons(byte[] beaconHeader) { + this.enqueueBeacon = beaconHeader; + } + + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementTA#stopEnqueueingBeacons() + */ + @Override + public void stopEnqueueingBeacons() { + this.enqueueBeacon = null; + } + + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementTA#startMultipleBeaconing(byte[], int) + */ + @Override + public void startMultipleBeaconing(byte[] beaconHeader, int nbNeighbours) { + /* TODO: Multiple beacons */ + } + + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementTA#stopMultipleBeaconing() + */ + @Override + public void stopMultipleBeaconing() { + /* TODO: Multiple beacons */ + } - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementTA#getLongPositionVector(byte[]) - */ - @Override - public byte[] getLongPositionVector(byte[] targetGnAddress) { - byte[] mid = ByteHelper.extract(targetGnAddress, 2, 6); - long key = ByteHelper.byteArrayToLong(mid); - for(int i = 0; i < GET_LPV_TIMEOUT; ++i) { - if (locTable.containsKey(key)) { - ITuple entry = locTable.get(key); - return entry.getB(); - } - try { + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementTA#getLongPositionVector(byte[]) + */ + @Override + public byte[] getLongPositionVector(byte[] targetGnAddress) { + byte[] mid = ByteHelper.extract(targetGnAddress, 2, 6); +// System.out.println("getLongPositionVector: Looking for Loc Entry: " + ByteHelper.byteArrayToString(mid)); + long key = ByteHelper.byteArrayToLong(mid); + for(int i = 0; i < GET_LPV_TIMEOUT; ++i) { + if (locTable.containsKey(key)) { + ITuple entry = locTable.get(key); + return entry.getB(); + } + try { Thread.sleep(GET_LPV_POLL_INTERVAL); } catch (InterruptedException e) { // Do nothing, we do not care } - } - return null; - } + } + return null; + } - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementLayers#getGnBeacon() - */ - @Override - public byte[] getGnBeacon() { - return beaconHeader; - } - - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementLayers#getGnBeaconInterval() - */ - @Override - public int getGnBeaconInterval() { - return GN_BEACON_INTERVAL; - } + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementLayers#getGnBeacon() + */ + @Override + public byte[] getGnBeacon() { + return beaconHeader; + } + + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementLayers#getGnBeaconInterval() + */ + @Override + public int getGnBeaconInterval() { + return GN_BEACON_INTERVAL; + } - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementLayers#getGnEnqueueBeacon() - */ - @Override - public byte[] getGnEnqueueBeacon() { - return enqueueBeacon; - } + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementLayers#getGnEnqueueBeacon() + */ + @Override + public byte[] getGnEnqueueBeacon() { + return enqueueBeacon; + } - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementLayers#gnUpdateLocTable(byte[], long, byte[]) - */ - @Override - public void gnUpdateLocTable(byte[] mid, long timestamp, byte[] lpv) { - // Java does not provide unsigned int - timestamp &= 0xffffffffL; - long key = ByteHelper.byteArrayToLong(mid); - ITuple entry = locTable.get(key); - if(entry == null || entry.getA() < timestamp) { - //ByteHelper.dump("Adding Loc Entry for: ", mid); - locTable.put(key, new Tuple(timestamp, lpv)); - } - } + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementLayers#gnUpdateLocTable(byte[], long, byte[]) + */ + @Override + public void gnUpdateLocTable(byte[] mid, long timestamp, byte[] lpv) { + // Java does not provide unsigned int + timestamp &= 0xffffffffL; + long key = ByteHelper.byteArrayToLong(mid); + ITuple entry = locTable.get(key); + if(entry == null || entry.getA() < timestamp) { +// System.out.println("gnUpdateLocTable: Adding Loc Entry for: " + ByteHelper.byteArrayToString(mid)); + locTable.put(key, new Tuple(timestamp, lpv)); + } + } - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementLayers#getLinkLayerAddress() - */ - @Override - public byte[] getLinkLayerAddress() { - return linkLayerAddress; - } - - /* (non-Javadoc) + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementLayers#getLinkLayerAddress() + */ + @Override + public byte[] getLinkLayerAddress() { + return linkLayerAddress; + } + + /* (non-Javadoc) * @see org.etsi.its.adapter.IManagementLayers#getLinkLayerAddress() */ @Override @@ -230,44 +291,44 @@ public class Management implements IManagementTA, IManagementLayers { this.linkLayerAddress = linkLayerAddress; } - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementLayers#getLatitude() - */ - @Override - public byte[] getLatitude() { - return ByteHelper.intToByteArray(latitude, 4); - } + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementLayers#getLatitude() + */ + @Override + public byte[] getLatitude() { + return ByteHelper.intToByteArray(latitude, 4); + } - /* (non-Javadoc) - * @see org.etsi.its.adapter.IManagementLayers#getLongitude() - */ - @Override - public byte[] getLongitude() { - return ByteHelper.intToByteArray(longitude, 4); - } - - /** - * Set to null in order to prevent Test Adapter from sending beacons - * Otherwise, it shall be set to a valid encoded beacon header to be send periodically by Test Adapter - * @see startEnqueueingBeacons - * @see stopEnqueueingBeacons - */ - private byte[] beaconHeader = null; - - /** - * Set to null if received Beacon messages have to be discarded by test adapter (= not enqueued) - * Otherwise, it shall be set to the to an encoded beacon header value acting as a filter for enqueueing received beacons + /* (non-Javadoc) + * @see org.etsi.its.adapter.IManagementLayers#getLongitude() + */ + @Override + public byte[] getLongitude() { + return ByteHelper.intToByteArray(longitude, 4); + } + + /** + * Set to null in order to prevent Test Adapter from sending beacons + * Otherwise, it shall be set to a valid encoded beacon header to be send periodically by Test Adapter + * @see startEnqueueingBeacons + * @see stopEnqueueingBeacons + */ + private byte[] beaconHeader = null; + + /** + * Set to null if received Beacon messages have to be discarded by test adapter (= not enqueued) + * Otherwise, it shall be set to the to an encoded beacon header value acting as a filter for enqueueing received beacons * @see startBeaconing * @see stopBeaconing - */ - private byte[] enqueueBeacon = null; - - /** - * Table used to store neighbours (= SUT) position vectors - * @see gnUpdateLocTable - * @see getLongPositionVector - */ - private static Map> locTable = new HashMap>(); + */ + private byte[] enqueueBeacon = null; + + /** + * Table used to store neighbours (= SUT) position vectors + * @see gnUpdateLocTable + * @see getLongPositionVector + */ + private static Map> locTable = new HashMap>(); /* (non-Javadoc) * @see org.etsi.its.adapter.IManagementLayers#registerBeaconThread(java.lang.Thread) @@ -281,4 +342,90 @@ public class Management implements IManagementTA, IManagementLayers { enqueueBeacon = null; } -} + @Override + public void setSecuredMode(final byte[] securityData) { + certificateId = ByteHelper.byteArrayWithLengthToString(ByteHelper.concat(ByteHelper.intToByteArray(securityData.length, 4), securityData)); + setupSecuredMode(); + } + + @Override + public void unsetSecuredMode() { + securedMode = false; + signingPrivateKey = null; + signingPublicKeyX = null; + signingPublicKeyY = null; + atCertificate = null; + atCertificateDigest = null; + } + + @Override + public boolean isSecuredModeSet() { + return securedMode; + } + + @Override + public BigInteger getSigningPrivateKey() { + return new BigInteger(signingPrivateKey); + } + + @Override + public byte[] getSigningPublicKeyX() { + return signingPublicKeyX; + } + + @Override + public byte[] getSigningPublicKeyY() { + return signingPublicKeyY; + } + + @Override + public byte[] getAtCertificate() { + return atCertificate; + } + + @Override + public byte[] getAtCertificateDigest() { + return atCertificateDigest; + } + + /** + * @desc This method setup secured mode according to the Test adapter settings (@see TsSecuredMode flags). + * The secured mode could be overrided by test case secured mode configuration through AC primitives + * @remark This method shall be called by the constructor only + */ + private void setupSecuredMode() { +// System.out.println(System.getProperty("user.dir")); + securedMode = true; + ICertificatesIO _certCache = CertificatesIOFactory.getInstance(); + if (!_certCache.loadCertificates(TsSecuredRootPath, TsSecuredConfiId)) { + securedMode = false; + } else { + ByteArrayOutputStream certificate = new ByteArrayOutputStream(); + _certCache.readCertificate(certificateId + ".AT_CERT", certificate); + // Extract public keys + atCertificate = certificate.toByteArray(); +// System.out.println("Management.setupSecuredModeFromTaConfig: certificate=" + ByteHelper.byteArrayToString(value)); + atCertificateDigest = new byte[8]; + System.arraycopy(atCertificate, 3, atCertificateDigest, 0, 8); +// System.out.println("Management.setupSecuredModeFromTaConfig: atCertificateDigest=" + ByteHelper.byteArrayToString(atCertificateDigest)); + int offset = 18; + // KeyX + signingPublicKeyX = new byte[32]; + System.arraycopy(atCertificate, offset, signingPublicKeyX, 0, 32); + offset += 32; +// System.out.println("Management.setupSecuredModeFromTaConfig: certificate=" + ByteHelper.byteArrayToString(signingPublicKeyX)); + // KeyY + signingPublicKeyY = new byte[32]; + System.arraycopy(atCertificate, offset, signingPublicKeyY, 0, 32); +// System.out.println("Management.setupSecuredModeFromTaConfig: certificate=" + ByteHelper.byteArrayToString(signingPublicKeyY)); + // Extract private keys + ByteArrayOutputStream signingPrivateKey = new ByteArrayOutputStream(); + ByteArrayOutputStream encryptPrivateKey = new ByteArrayOutputStream(); + _certCache.readPrivateKeys(certificateId + ".PRIVATE_KEYS", signingPrivateKey, encryptPrivateKey); + this.signingPrivateKey = signingPrivateKey.toByteArray().clone(); +// System.out.println("Management.setupSecuredModeFromTaConfig: signingPrivateKey=" + ByteHelper.byteArrayToString(this.signingPrivateKey)); + // TODO Add support of encryption + } + } + +} // End of class Management diff --git a/javasrc/adapter/org/etsi/its/adapter/PcapMultiplexer.java b/javasrc/adapter/org/etsi/its/adapter/PcapMultiplexer.java index 802337a4f..cc8d976a2 100644 --- a/javasrc/adapter/org/etsi/its/adapter/PcapMultiplexer.java +++ b/javasrc/adapter/org/etsi/its/adapter/PcapMultiplexer.java @@ -72,7 +72,7 @@ public class PcapMultiplexer implements Runnable { } device = alldevs.get(ifaceIndex); - System.out.println("Listening: " + device.getName()); +// System.out.println("Listening: " + device.getName()); } /** @@ -84,13 +84,10 @@ public class PcapMultiplexer implements Runnable { } public synchronized void register(Layer client, byte[] macAddress, short frameType) { +// System.out.println(">>>PcapMultiplexer.registering: " + frameType); - System.out.println("Registering client, " + frameType); if(clientsToMacs.isEmpty()) { - System.out.println("First Client !"); - // Open interface - int snaplen = 64 * 1024; // Capture all packets, no truncation int flags = Pcap.MODE_PROMISCUOUS; // capture all packets int timeout = 10; // 10 millis @@ -106,7 +103,7 @@ public class PcapMultiplexer implements Runnable { filter = ""; } else { - System.out.println("Another Client !"); +// System.out.println("Another Client !"); filter = filter + " and "; } @@ -117,7 +114,7 @@ public class PcapMultiplexer implements Runnable { } filter = filter + "not ether src " + strMacAddress; - System.out.println("New filter: " + filter); +// System.out.println("New filter: " + filter); // Apply filter PcapBpfProgram bpfFilter = new PcapBpfProgram(); @@ -125,7 +122,7 @@ public class PcapMultiplexer implements Runnable { int netmask = 0; int r = pcap.compile(bpfFilter, filter, optimize, netmask); if (r != Pcap.OK) { - System.out.println("Filter error: " + pcap.getErr()); +// System.out.println("Filter error: " + pcap.getErr()); } pcap.setFilter(bpfFilter); @@ -198,7 +195,7 @@ public class PcapMultiplexer implements Runnable { } } } - + } }; diff --git a/javasrc/adapter/org/etsi/its/adapter/TestAdapter.java b/javasrc/adapter/org/etsi/its/adapter/TestAdapter.java index e00633a5f..9bf747afe 100644 --- a/javasrc/adapter/org/etsi/its/adapter/TestAdapter.java +++ b/javasrc/adapter/org/etsi/its/adapter/TestAdapter.java @@ -40,286 +40,286 @@ import org.etsi.ttcn.tri.TriTestCaseId; @SuppressWarnings({ "serial", "deprecation" }) public class TestAdapter implements TriCommunicationSA, Observer { - /** - * Mapping (component-) support for layered port - */ - protected ComponentMgr compPortMgr; - - /** - * Provides all TE related interfaces - */ - protected ITERequired required; - - /** - * Constructor - */ - public TestAdapter() { - super(); - - compPortMgr = new ComponentMgr(this); - required = TERFactory.getInstance(); - } - - /** - * This method will force a Test adapter reset - * @see org.etsi.ttcn.tri.TriCommunicationSA#triEndTestCase() - */ - @Override - public TriStatus triEndTestCase() { - triSAReset(); - return required.getTriStatus(TriStatus.TRI_OK); - } - - /* (non-Javadoc) - * @see org.etsi.ttcn.tri.TriCommunicationSA#triExecuteTestcase(org.etsi.ttcn.tri.TriTestCaseId, org.etsi.ttcn.tri.TriPortIdList) - */ - @Override + /** + * Mapping (component-) support for layered port + */ + protected ComponentMgr compPortMgr; + + /** + * Provides all TE related interfaces + */ + protected ITERequired required; + + /** + * Constructor + */ + public TestAdapter() { + super(); + + compPortMgr = new ComponentMgr(this); + required = TERFactory.getInstance(); + } + + /** + * This method will force a Test adapter reset + * @see org.etsi.ttcn.tri.TriCommunicationSA#triEndTestCase() + */ + @Override + public TriStatus triEndTestCase() { + triSAReset(); + return required.getTriStatus(TriStatus.TRI_OK); + } + + /* (non-Javadoc) + * @see org.etsi.ttcn.tri.TriCommunicationSA#triExecuteTestcase(org.etsi.ttcn.tri.TriTestCaseId, org.etsi.ttcn.tri.TriPortIdList) + */ + @Override public TriStatus triExecuteTestcase(final TriTestCaseId tcId, final TriPortIdList portList) { - return required.getTriStatus(TriStatus.TRI_OK); - } + return required.getTriStatus(TriStatus.TRI_OK); + } - /* (non-Javadoc) - * @see org.etsi.ttcn.tri.TriCommunicationSA#triMap(org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriPortId) - */ - @Override + /* (non-Javadoc) + * @see org.etsi.ttcn.tri.TriCommunicationSA#triMap(org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriPortId) + */ + @Override public TriStatus triMap(final TriPortId compPortId, final TriPortId tsiPortId) { - IPort port; - String portName = tsiPortId.getPortName(); - String ComponentId = compPortId.getComponent().getComponentId(); - - if (tsiPortId.getPortName().equals("acPort")) { - port = new AdapterControlPort(portName, ComponentId); - } else if (tsiPortId.getPortName().equals("utPort")) { - port = new UpperTesterPort(portName, ComponentId); - } else { - String componentName = compPortId.getComponent().getComponentName(); - - // Dirty hack due to LinkLayer_MTC removal. - if(componentName.equalsIgnoreCase("MTC")) { - componentName = "NodeB"; - } - - port = ProtocolPortFactory.getInstance().createPort( - tsiPortId.getPortName(), - ComponentId, - ((CharstringValue)required.getTaParameter(portName)).getString(), - ((CharstringValue)required.getTaParameter("LinkLayer_" + componentName)).getString()); - } - - compPortMgr.addComponent(compPortId.getComponent()); - compPortMgr.addPort(ComponentId, tsiPortId, port); - - return required.getTriStatus(TriStatus.TRI_OK); - } - - /** - * This method will force port unmapping - * @see org.etsi.ttcn.tri.TriCommunicationSA#triSAReset() - */ - @Override - public TriStatus triSAReset() { - - // Force port unmapping - compPortMgr.removeAllPorts(); - - return required.getTriStatus(TriStatus.TRI_OK); - } - - /* (non-Javadoc) - * @see org.etsi.ttcn.tri.TriCommunicationSA#triSend(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddress, org.etsi.ttcn.tri.TriMessage) - */ - @Override + IPort port; + String portName = tsiPortId.getPortName(); + String ComponentId = compPortId.getComponent().getComponentId(); + + if (tsiPortId.getPortName().equals("acPort")) { + port = new AdapterControlPort(portName, ComponentId); + } else if (tsiPortId.getPortName().toLowerCase().endsWith("utport")) { + port = new UpperTesterPort(portName, ComponentId); + } else { + String componentName = compPortId.getComponent().getComponentName(); + + // Dirty hack due to LinkLayer_MTC removal. + if(componentName.equalsIgnoreCase("MTC")) { + componentName = "NodeB"; + } + + port = ProtocolPortFactory.getInstance().createPort( + tsiPortId.getPortName(), + ComponentId, + ((CharstringValue)required.getTaParameter(portName)).getString(), + ((CharstringValue)required.getTaParameter("LinkLayer_" + componentName)).getString()); + } + + compPortMgr.addComponent(compPortId.getComponent()); + compPortMgr.addPort(ComponentId, tsiPortId, port); + + return required.getTriStatus(TriStatus.TRI_OK); + } + + /** + * This method will force port unmapping + * @see org.etsi.ttcn.tri.TriCommunicationSA#triSAReset() + */ + @Override + public TriStatus triSAReset() { + + // Force port unmapping + compPortMgr.removeAllPorts(); + + return required.getTriStatus(TriStatus.TRI_OK); + } + + /* (non-Javadoc) + * @see org.etsi.ttcn.tri.TriCommunicationSA#triSend(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddress, org.etsi.ttcn.tri.TriMessage) + */ + @Override public TriStatus triSend(TriComponentId componentId, TriPortId tsiPortId, TriAddress address, TriMessage message) { - IPort port = compPortMgr.getPort(componentId.getComponentId(), tsiPortId.getPortName()); - if (port == null) { - return required.getTriStatus(TriStatus.TRI_ERROR, "Unknown port"); - } - - port.send(message.getEncodedMessage()); - return required.getTriStatus(TriStatus.TRI_OK); - } - - /* (non-Javadoc) - * @see org.etsi.ttcn.tri.TriCommunicationSA#triSendBC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriMessage) - */ - @Override - public TriStatus triSendBC(TriComponentId componentId, TriPortId portId, TriMessage message) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triSendBC not implemented"); - } - - /* (non-Javadoc) - * @see org.etsi.ttcn.tri.TriCommunicationSA#triSendMC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddressList, org.etsi.ttcn.tri.TriMessage) - */ - @Override + IPort port = compPortMgr.getPort(componentId.getComponentId(), tsiPortId.getPortName()); + if (port == null) { + return required.getTriStatus(TriStatus.TRI_ERROR, "Unknown port"); + } + + port.send(message.getEncodedMessage()); + return required.getTriStatus(TriStatus.TRI_OK); + } + + /* (non-Javadoc) + * @see org.etsi.ttcn.tri.TriCommunicationSA#triSendBC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriMessage) + */ + @Override + public TriStatus triSendBC(TriComponentId componentId, TriPortId portId, TriMessage message) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triSendBC not implemented"); + } + + /* (non-Javadoc) + * @see org.etsi.ttcn.tri.TriCommunicationSA#triSendMC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddressList, org.etsi.ttcn.tri.TriMessage) + */ + @Override public TriStatus triSendMC(TriComponentId componentId, TriPortId portId, TriAddressList addressList, TriMessage message) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triSendMC not implemented"); - } - - /* (non-Javadoc) - * @see org.etsi.ttcn.tri.TriCommunicationSA#triUnmap(org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriPortId) - */ - @Override - public TriStatus triUnmap(final TriPortId compPortId, final TriPortId tsiPortId) { - - compPortMgr.removePort(compPortId.getComponent().getComponentId(), tsiPortId.getPortName()); - - return required.getTriStatus(TriStatus.TRI_OK); - } - - /** - * Enqueues a message on the specified port - * @param tsiPort Port where the message will be enqueued - * @param sutAddress SUT address - * @param receiverComp Component on which port the message will be enqueued - * @param rcvMessage Message to be enqueued - */ - private void enqueueMsg(TriPortId tsiPort, TriAddress sutAddress, TriComponentId receiverComp, TriMessage rcvMessage) { - - required.getCommunicationTE().triEnqueueMsg(tsiPort, sutAddress, receiverComp, rcvMessage); - } - - /* (non-Javadoc) - * @see java.util.Observer#update(java.util.Observable, java.lang.Object) - */ - @Override - public void update(Observable o, Object context) { - - if(context instanceof PortEvent) { - // Extract context - PortEvent p = (PortEvent)context; - TriPortId port = null; - TriComponentId compId = null; - - port = (TriPortId)compPortMgr.getPortId(p.getComponentName(), p.getPortName()); - compId = compPortMgr.getComponent(p.getComponentName()); - - // Enqueue message - if (port != null) { - enqueueMsg( - port, - required.getTriAddress(new byte[] { }), - compId, - required.getTriMessage(p.get_message())); - } - } - } // End of method update - - /** - * TriCall not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triCall(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddress, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriParameterList) - */ - @Override - public TriStatus triCall(TriComponentId componentId, TriPortId tsiPortId, TriAddress sutAddress, TriSignatureId signatureId, TriParameterList parameterList) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triCall not implemented"); - } - - /** - * TriCallBC not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triCallBC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriParameterList) - */ - @Override - public TriStatus triCallBC(TriComponentId componentId, TriPortId tsiPortId, TriSignatureId signatureId, TriParameterList parameterList) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triCallBC not implemented"); - } - - /** - * TriCallMC not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triCallMC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddressList, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriParameterList) - */ - @Override - public TriStatus triCallMC(TriComponentId componentId, TriPortId tsiPortId, TriAddressList sutAddresses, TriSignatureId signatureId, TriParameterList parameterList) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triCallMC not implemented"); - } - - /** - * triRaise not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triRaise(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddress, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriException) - */ - @Override - public TriStatus triRaise(TriComponentId componentId, TriPortId tsiPortId, TriAddress sutAddress, TriSignatureId signatureId, TriException exception) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triRaise not implemented"); - } - - /** - * triRaiseBC not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triRaiseBC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriException) - */ - @Override - public TriStatus triRaiseBC(TriComponentId componentId, TriPortId tsitPortId, TriSignatureId signatureId, TriException exc) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triRaiseBC not implemented"); - } - - /** - * triRaiseMC not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triRaiseMC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddressList, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriException) - */ - @Override - public TriStatus triRaiseMC(TriComponentId componentId, TriPortId tsitPortId, TriAddressList sutAddresses, TriSignatureId signatureId, TriException exc) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triRaiseMC not implemented"); - } - - /** - * triReply not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triReply(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddress, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriParameterList, org.etsi.ttcn.tri.TriParameter) - */ - @Override - public TriStatus triReply(TriComponentId componentId, TriPortId tsiPortId, TriAddress sutAddress, TriSignatureId signatureId, TriParameterList parameterList, TriParameter returnValue) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triReply not implemented"); - } - - /** - * triReplyBC not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triReplyBC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriParameterList, org.etsi.ttcn.tri.TriParameter) - */ - @Override - public TriStatus triReplyBC(TriComponentId componentId, TriPortId tsiPortId, TriSignatureId signatureId, TriParameterList parameterList, TriParameter returnValue) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triReplyBCnot implemented"); - } - - /** - * triReplyMC not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triReplyMC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddressList, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriParameterList, org.etsi.ttcn.tri.TriParameter) - */ - @Override - public TriStatus triReplyMC(TriComponentId componentId, TriPortId tsiPortId, TriAddressList sutAddresses, TriSignatureId signatureId, TriParameterList parameterList, TriParameter returnValue) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triReplyMC not implemented"); - } - - /** - * triSutActionInformal not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triSutActionInformal(java.lang.String) - */ - @Override - public TriStatus triSutActionInformal(String description) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triSutActionInformal not implemented"); - } - - /** - * triSutActionTemplate not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triSutActionTemplate(org.etsi.ttcn.tri.TriActionTemplate) - */ - @Override - public TriStatus triSutActionTemplate(TriActionTemplate templateValue) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triSutActionTemplate not implemented"); - } - - /** + return required.getTriStatus(TriStatus.TRI_ERROR, "triSendMC not implemented"); + } + + /* (non-Javadoc) + * @see org.etsi.ttcn.tri.TriCommunicationSA#triUnmap(org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriPortId) + */ + @Override + public TriStatus triUnmap(final TriPortId compPortId, final TriPortId tsiPortId) { + + compPortMgr.removePort(compPortId.getComponent().getComponentId(), tsiPortId.getPortName()); + + return required.getTriStatus(TriStatus.TRI_OK); + } + + /** + * Enqueues a message on the specified port + * @param tsiPort Port where the message will be enqueued + * @param sutAddress SUT address + * @param receiverComp Component on which port the message will be enqueued + * @param rcvMessage Message to be enqueued + */ + private void enqueueMsg(TriPortId tsiPort, TriAddress sutAddress, TriComponentId receiverComp, TriMessage rcvMessage) { + + required.getCommunicationTE().triEnqueueMsg(tsiPort, sutAddress, receiverComp, rcvMessage); + } + + /* (non-Javadoc) + * @see java.util.Observer#update(java.util.Observable, java.lang.Object) + */ + @Override + public void update(Observable o, Object context) { + + if(context instanceof PortEvent) { + // Extract context + PortEvent p = (PortEvent)context; + TriPortId port = null; + TriComponentId compId = null; + + port = (TriPortId)compPortMgr.getPortId(p.getComponentName(), p.getPortName()); + compId = compPortMgr.getComponent(p.getComponentName()); + + // Enqueue message + if (port != null) { + enqueueMsg( + port, + required.getTriAddress(new byte[] { }), + compId, + required.getTriMessage(p.get_message())); + } + } + } // End of method update + + /** + * TriCall not implemented + * @see org.etsi.ttcn.tri.TriCommunicationSA#triCall(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddress, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriParameterList) + */ + @Override + public TriStatus triCall(TriComponentId componentId, TriPortId tsiPortId, TriAddress sutAddress, TriSignatureId signatureId, TriParameterList parameterList) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triCall not implemented"); + } + + /** + * TriCallBC not implemented + * @see org.etsi.ttcn.tri.TriCommunicationSA#triCallBC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriParameterList) + */ + @Override + public TriStatus triCallBC(TriComponentId componentId, TriPortId tsiPortId, TriSignatureId signatureId, TriParameterList parameterList) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triCallBC not implemented"); + } + + /** + * TriCallMC not implemented + * @see org.etsi.ttcn.tri.TriCommunicationSA#triCallMC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddressList, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriParameterList) + */ + @Override + public TriStatus triCallMC(TriComponentId componentId, TriPortId tsiPortId, TriAddressList sutAddresses, TriSignatureId signatureId, TriParameterList parameterList) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triCallMC not implemented"); + } + + /** + * triRaise not implemented + * @see org.etsi.ttcn.tri.TriCommunicationSA#triRaise(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddress, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriException) + */ + @Override + public TriStatus triRaise(TriComponentId componentId, TriPortId tsiPortId, TriAddress sutAddress, TriSignatureId signatureId, TriException exception) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triRaise not implemented"); + } + + /** + * triRaiseBC not implemented + * @see org.etsi.ttcn.tri.TriCommunicationSA#triRaiseBC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriException) + */ + @Override + public TriStatus triRaiseBC(TriComponentId componentId, TriPortId tsitPortId, TriSignatureId signatureId, TriException exc) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triRaiseBC not implemented"); + } + + /** + * triRaiseMC not implemented + * @see org.etsi.ttcn.tri.TriCommunicationSA#triRaiseMC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddressList, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriException) + */ + @Override + public TriStatus triRaiseMC(TriComponentId componentId, TriPortId tsitPortId, TriAddressList sutAddresses, TriSignatureId signatureId, TriException exc) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triRaiseMC not implemented"); + } + + /** + * triReply not implemented + * @see org.etsi.ttcn.tri.TriCommunicationSA#triReply(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddress, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriParameterList, org.etsi.ttcn.tri.TriParameter) + */ + @Override + public TriStatus triReply(TriComponentId componentId, TriPortId tsiPortId, TriAddress sutAddress, TriSignatureId signatureId, TriParameterList parameterList, TriParameter returnValue) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triReply not implemented"); + } + + /** + * triReplyBC not implemented + * @see org.etsi.ttcn.tri.TriCommunicationSA#triReplyBC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriParameterList, org.etsi.ttcn.tri.TriParameter) + */ + @Override + public TriStatus triReplyBC(TriComponentId componentId, TriPortId tsiPortId, TriSignatureId signatureId, TriParameterList parameterList, TriParameter returnValue) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triReplyBCnot implemented"); + } + + /** + * triReplyMC not implemented + * @see org.etsi.ttcn.tri.TriCommunicationSA#triReplyMC(org.etsi.ttcn.tri.TriComponentId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriAddressList, org.etsi.ttcn.tri.TriSignatureId, org.etsi.ttcn.tri.TriParameterList, org.etsi.ttcn.tri.TriParameter) + */ + @Override + public TriStatus triReplyMC(TriComponentId componentId, TriPortId tsiPortId, TriAddressList sutAddresses, TriSignatureId signatureId, TriParameterList parameterList, TriParameter returnValue) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triReplyMC not implemented"); + } + + /** + * triSutActionInformal not implemented + * @see org.etsi.ttcn.tri.TriCommunicationSA#triSutActionInformal(java.lang.String) + */ + @Override + public TriStatus triSutActionInformal(String description) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triSutActionInformal not implemented"); + } + + /** + * triSutActionTemplate not implemented + * @see org.etsi.ttcn.tri.TriCommunicationSA#triSutActionTemplate(org.etsi.ttcn.tri.TriActionTemplate) + */ + @Override + public TriStatus triSutActionTemplate(TriActionTemplate templateValue) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triSutActionTemplate not implemented"); + } + + /** * triMapParam not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triMapParam(org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriParameterList) - */ - @Override - public TriStatus triMapParam(TriPortId compPortId, TriPortId tsiPortId, TriParameterList paramList) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triMapParam not implemented"); - } - - /** + * @see org.etsi.ttcn.tri.TriCommunicationSA#triMapParam(org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriParameterList) + */ + @Override + public TriStatus triMapParam(TriPortId compPortId, TriPortId tsiPortId, TriParameterList paramList) { + return required.getTriStatus(TriStatus.TRI_ERROR, "triMapParam not implemented"); + } + + /** * triUnmapParam not implemented - * @see org.etsi.ttcn.tri.TriCommunicationSA#triUnmapParam(org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriParameterList) - */ - @Override + * @see org.etsi.ttcn.tri.TriCommunicationSA#triUnmapParam(org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriPortId, org.etsi.ttcn.tri.TriParameterList) + */ + @Override public TriStatus triUnmapParam(TriPortId compPortId, TriPortId tsiPortId, TriParameterList paramList) { - return required.getTriStatus(TriStatus.TRI_ERROR, "triUnmapParam not implemented"); - } + return required.getTriStatus(TriStatus.TRI_ERROR, "triUnmapParam not implemented"); + } } diff --git a/javasrc/adapter/org/etsi/its/adapter/TlsHelper.java b/javasrc/adapter/org/etsi/its/adapter/TlsHelper.java new file mode 100644 index 000000000..c9bd2f0c0 --- /dev/null +++ b/javasrc/adapter/org/etsi/its/adapter/TlsHelper.java @@ -0,0 +1,77 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.its.adapter; + +import java.io.ByteArrayInputStream; + +import org.etsi.ttcn.common.ByteHelper; + +public class TlsHelper { + + private static TlsHelper Instance = new TlsHelper(); + + public static TlsHelper getInstance() { return Instance; } + + private TlsHelper() { + } + + public byte[] size2tls(final int length) { + byte[] result = null; + if (length < 128) { // One byte length + result = new byte[] { (byte)length }; + } else { + long lv = length; + long bitLen = bitLength(lv); + long byteLen = byteLength(bitLen); + long flags = (long) ((byteLen | 1) << (byteLen * Byte.SIZE - bitLength(byteLen) - 1)); + long len = (long) (byteLen << (byteLen * Byte.SIZE - bitLength(byteLen) - 1)); + if ((flags & lv) != 0) { // We can encode the length on the MSB part + byteLen += 1; + len = (long) (byteLen << (byteLen * Byte.SIZE - bitLength(byteLen)) - 1); + } + result = ByteHelper.longToByteArray((long)(lv | len), (int) byteLen); + } + + return result; + } + + public long tls2size(final ByteArrayInputStream buf) { + // Sanity check + if (buf.available() == 0) { + return 0; + } + + // Read the first byte + byte msb = (byte) buf.read(); + if ((msb & 0x80) == 0x00) { // Integer < 128 + return msb; + } else { + // Decode the length. The encoding of the length shall use at most 7 bits set to 1 (see Draft ETSI TS 103 097 V1.1.14 Clause 4.1 Presentation Language Table 1/8) + byte bit; + byte byteLen = 1; + do { + bit = (byte) ((byte) (msb << byteLen++) & 0x80); + } while (bit != 0x00); + // Set the IntX length + byte[] data = new byte[byteLen - 1]; + buf.read(data, 0, byteLen - 1); + byte[] length = ByteHelper.concat(new byte[] { msb }, data); + length[0] &= (byte)(Math.pow(2.0, 8 - byteLen + 1) - 1); + long lv = ByteHelper.byteArrayToLong(length); + return lv; + } + } + + public long bitLength(final long value) { + return (long) Math.ceil(Math.log(value) / Math.log(2)); + } + + public long byteLength(final long value) { + double d = value; // Convert int to double + return (long) Math.ceil(d / Byte.SIZE); + } + +} // End of class TlsHelper diff --git a/javasrc/adapter/org/etsi/its/adapter/layers/GnLayer.java b/javasrc/adapter/org/etsi/its/adapter/layers/GnLayer.java index 546369ab2..5c9908ba6 100644 --- a/javasrc/adapter/org/etsi/its/adapter/layers/GnLayer.java +++ b/javasrc/adapter/org/etsi/its/adapter/layers/GnLayer.java @@ -18,107 +18,109 @@ import org.etsi.common.ByteHelper; import org.etsi.its.adapter.IManagementLayers; import org.etsi.ttcn.tci.CharstringValue; +import de.fraunhofer.sit.c2x.CryptoLib; + /** * Implementation of ITS GeoNetworking layer (background thread) */ public class GnLayer extends Layer implements Runnable, IEthernetSpecific { - - /** - * Implemented version of GeoNetworking specification - */ - private static final int GN_VERSION = 0; + + /** + * Implemented version of GeoNetworking specification + */ + private static final int GN_VERSION = 0; - /** + /** * Parameter name for GeoNetworking packet type */ - public static final String GN_TYPE = "GnType"; + public static final String GN_TYPE = "GnType"; - /** + /** * Parameter name for GeoNetworking packet sub-type */ - public static final String GN_SUBTYPE = "GnSubType"; + public static final String GN_SUBTYPE = "GnSubType"; - /** + /** * Parameter name for GeoNetworking payload type */ - public static final String GN_NEXTHEADER = "GnNextHeader"; + public static final String GN_NEXTHEADER = "GnNextHeader"; /** * Parameter name for destination position vector */ - public static final String GN_DEPV = "GnDePV"; + public static final String GN_DEPV = "GnDePV"; /** * Parameter name for Location Service's Target GN_Address */ - public static final String GN_TARGETGNADDR = "GnTargetGnAddress"; + public static final String GN_TARGETGNADDR = "GnTargetGnAddress"; /** * Parameter name for destination area's latitude */ - public static final String GN_LATITUDE = "GnLatitude"; + public static final String GN_LATITUDE = "GnLatitude"; /** * Parameter name for destination area's longitude */ - public static final String GN_LONGITUDE = "GnLongitude"; + public static final String GN_LONGITUDE = "GnLongitude"; /** * Parameter name for destination area's distance A */ - public static final String GN_DISTANCEA = "GnDistanceA"; + public static final String GN_DISTANCEA = "GnDistanceA"; /** * Parameter name for destination area's distance B */ - public static final String GN_DISTANCEB = "GnDistanceB"; + public static final String GN_DISTANCEB = "GnDistanceB"; /** * Parameter name for destination area's angle */ - public static final String GN_ANGLE = "GnAngle"; - + public static final String GN_ANGLE = "GnAngle"; + - /** + /** * GeoNetworking header type for unknown messages */ - public static final int HT_ANY = 0; - - /** + public static final int HT_ANY = 0; + + /** * GeoNetworking header type for beacon messages */ public static final int HT_BEACON = 1; - + /** * GeoNetworking header type for GeoUnicast messages */ public static final int HT_GEOUNICAST = 2; - + /** * GeoNetworking header type for GeoAnycast messages */ public static final int HT_GEOANYCAST = 3; - + /** * GeoNetworking header type for GeoBroadcast messages */ public static final int HT_GEOBROADCAST = 4; - + /** * GeoNetworking header type for Topology-scoped broadcast messages */ public static final int HT_TSB = 5; - + /** * GeoNetworking header type for Location Service messages */ public static final int HT_LS = 6; - + /** * Unspecified GeoNetworking header sub-type */ - public static final int HST_UNSPECIFIED = 0; + public static final int HST_UNSPECIFIED = 0; /** * Circle sub-type for GeoBroadcast/GeoAnycast messages @@ -157,20 +159,20 @@ public class GnLayer extends Layer implements Runnable, IEthernetSpecific { private static final long ITS_REF_TIME = 1072915200000L; - /** + /** * Constructor * @param management Layer management instance * @param lowerStack Lower protocol stack */ - public GnLayer(IManagementLayers management, Stack lowerStack) { - super(management, lowerStack); - sequenceNumber = 0; - running = true; - beaconThread = new Thread(this); - beaconThread.start(); - } - - /* (non-Javadoc) + public GnLayer(IManagementLayers management, Stack lowerStack) { + super(management, lowerStack); + sequenceNumber = 0; + running = true; + beaconThread = new Thread(this); + beaconThread.start(); + } + + /* (non-Javadoc) * @see org.etsi.its.adapter.ports.IEthernetSpecific#getEthernetType() */ @Override @@ -181,176 +183,282 @@ public class GnLayer extends Layer implements Runnable, IEthernetSpecific { return iutEthernetTypeValue.shortValue(); } - /** + /** * Thread function for sending periodic beacons * @see java.lang.Runnable#run() */ - @Override - public void run() { - Map params = new HashMap(); - params.put(GN_TYPE, HT_BEACON); - while(running) { - if(management.getGnBeacon() != null) { - send(null, params); - } - try { - Thread.sleep(management.getGnBeaconInterval()); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - /* (non-Javadoc) - * @see org.etsi.its.adapter.layers.Layer#unregister(org.etsi.its.adapter.layers.Layer) - */ - @Override - public void unregister(Layer upperLayer) { - if(running) { - running = false; - try { - beaconThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - super.unregister(upperLayer); - } - - /* (non-Javadoc) - * @see org.etsi.its.adapter.layers.Layer#send(byte[], java.util.Map) - */ - @Override - public boolean send(byte[] message, Map params) { - - byte [] extHdr = null; - int ht; - int hst; - int hoplimit = 255; - - try { - ht = (Integer)params.get(GN_TYPE); - } - catch (NullPointerException e) { - ht = HT_ANY; - } - - try { - hst = (Integer)params.get(GN_SUBTYPE); - } - catch (NullPointerException e) { - hst = HST_UNSPECIFIED; - } - - switch(ht) { - case HT_LS: - if(hst == HST_LSREPLY) { - extHdr = createLsReplyHeader((byte[])params.get(GN_DEPV)); - } - else { - extHdr = createLsRequestHeader((byte[])params.get(GN_TARGETGNADDR)); - } - break; - case HT_GEOUNICAST: - extHdr = createGeoUnicastHeader((byte[])params.get(GN_DEPV)); - break; - case HT_TSB: - if(hst == HST_MULTIHOP) { - extHdr = createTsbHeader(); - } - else { - hoplimit = 1; - extHdr = createShbHeader(); - } - break; - case HT_GEOBROADCAST: - case HT_GEOANYCAST: - extHdr = createGeoBroadcastHeader( - (Long)params.get(GN_LATITUDE), - (Long)params.get(GN_LONGITUDE), - (Integer)params.get(GN_DISTANCEA), - (Integer)params.get(GN_DISTANCEB), - (Integer)params.get(GN_ANGLE) - ); - } - - byte[] basicHdr = createBasicHeader(); - byte[] commonHdr = createCommonHeader((String)params.get(GN_NEXTHEADER), ht, hst, (message == null)?0:message.length, hoplimit); - - return super.send(ByteHelper.concat(basicHdr, commonHdr, extHdr, message), params); - } - - /* (non-Javadoc) - * @see org.etsi.its.adapter.layers.Layer#receive(byte[]) - */ - @Override - public void receive(byte[] message, Map lowerInfo) { - - byte[] basicHdr = new byte[4]; // TODO To be removed - System.arraycopy(message, 4, basicHdr, 0, 4); - - byte[] versionNh = new byte[1]; - System.arraycopy(basicHdr, 0, versionNh, 0, 1); - int nextHeader = (int)(versionNh[0] & (byte)0x0F); + @Override + public void run() { + Map params = new HashMap(); + params.put(GN_TYPE, HT_BEACON); + while(running) { + if(management.getGnBeacon() != null) { + send(null, params); + } + try { + Thread.sleep(management.getGnBeaconInterval()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + /* (non-Javadoc) + * @see org.etsi.its.adapter.layers.Layer#unregister(org.etsi.its.adapter.layers.Layer) + */ + @Override + public void unregister(Layer upperLayer) { + if(running) { + running = false; + try { + beaconThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + super.unregister(upperLayer); + } - byte[] commonHdr = new byte[8]; - System.arraycopy(message, 4, commonHdr, 0, 8); - - byte[] htHst = new byte[1]; - System.arraycopy(commonHdr, 1, htHst, 0, 1); - int headerSubType = (int)(htHst[0] & (byte)0x0F); - int headerType = (int)(htHst[0] >> 4); - - byte[] pl = new byte[2]; - System.arraycopy(commonHdr, 4, pl , 0, 2); - int payloadLength = ByteHelper.byteArrayToInt(pl); - - if(headerType == HT_LS) { - // Process LS messages - if(headerSubType == HST_LSREQUEST) { - byte[] gnAddress = new byte[8]; - System.arraycopy(message, 68, gnAddress, 0, 8); - byte[] mid = new byte[6]; - System.arraycopy(gnAddress, 2, mid, 0, 6); - if(Arrays.equals(mid, management.getLinkLayerAddress()) == true) { - // Send LS Reply - byte[] depv = new byte[20]; - System.arraycopy(message, 40, depv, 0, 20); - - Map params = new HashMap(); - params.put(GN_DEPV, depv); - params.put(GN_TYPE, HT_LS); - params.put(GN_SUBTYPE, HST_LSREPLY); - send(null, params); - } - } - else { - // we are not interested in LS replies so far. - } - } - else { - // Other messages - if(payloadLength > 0) { - byte[] payload = new byte[payloadLength]; - System.arraycopy(message, message.length - payloadLength, payload, 0, payloadLength); - lowerInfo.put(GN_NEXTHEADER, nextHeader); - super.receive(payload, lowerInfo); - } - } - } + /* (non-Javadoc) + * @see org.etsi.its.adapter.layers.Layer#send(byte[], java.util.Map) + */ + @Override + public boolean send(byte[] message, Map params) { + + byte [] extHdr = null; + int ht; + int hst; + int hoplimit = 255; + + try { + ht = (Integer)params.get(GN_TYPE); + } + catch (NullPointerException e) { + ht = HT_ANY; + } + + try { + hst = (Integer)params.get(GN_SUBTYPE); + } + catch (NullPointerException e) { + hst = HST_UNSPECIFIED; + } - /** + switch(ht) { + case HT_LS: + if(hst == HST_LSREPLY) { + extHdr = createLsReplyHeader((byte[])params.get(GN_DEPV)); + } + else { + extHdr = createLsRequestHeader((byte[])params.get(GN_TARGETGNADDR)); + } + break; + case HT_GEOUNICAST: + extHdr = createGeoUnicastHeader((byte[])params.get(GN_DEPV)); + break; + case HT_TSB: + if(hst == HST_MULTIHOP) { + extHdr = createTsbHeader(); + } + else { + hoplimit = 1; + extHdr = createShbHeader(); + } + break; + case HT_GEOBROADCAST: + case HT_GEOANYCAST: + extHdr = createGeoBroadcastHeader( + (Long)params.get(GN_LATITUDE), + (Long)params.get(GN_LONGITUDE), + (Integer)params.get(GN_DISTANCEA), + (Integer)params.get(GN_DISTANCEB), + (Integer)params.get(GN_ANGLE) + ); + } + + byte[] toBeSent = null; + byte[] basicHdr = createBasicHeader(); + byte[] commonHdr = createCommonHeader((String)params.get(GN_NEXTHEADER), ht, hst, (message == null)?0:message.length, hoplimit); + if (!management.isSecuredModeSet()) { // Secure mode disabled + toBeSent = ByteHelper.concat(basicHdr, commonHdr, extHdr, message); + } else { + toBeSent = createSecuredMessage(basicHdr, commonHdr, extHdr, message); + } + + return super.send(toBeSent, params); + } + + /* (non-Javadoc) + * @see org.etsi.its.adapter.layers.Layer#receive(byte[]) + */ + @Override + public void receive(byte[] message, Map lowerInfo) { +// System.out.println(">>> GnLayer.receive: " + ByteHelper.byteArrayToString(message)); + + byte[] basicHdr = new byte[4]; // TODO To be removed + System.arraycopy(message, 4, basicHdr, 0, 4); + byte[] versionNh = new byte[1]; + System.arraycopy(basicHdr, 0, versionNh, 0, 1); + int nextHeader = (int)(versionNh[0] & (byte)0x0F); + + if (!management.isSecuredModeSet()) { // Secure mode disabled + byte[] commonHdr = new byte[8]; + System.arraycopy(message, 4, commonHdr, 0, 8); + + byte[] htHst = new byte[1]; + System.arraycopy(commonHdr, 1, htHst, 0, 1); + int headerSubType = (int)(htHst[0] & (byte)0x0F); + int headerType = (int)(htHst[0] >> 4); + + byte[] pl = new byte[2]; + System.arraycopy(commonHdr, 4, pl , 0, 2); + int payloadLength = ByteHelper.byteArrayToInt(pl); + + if(headerType == HT_LS) { + // Process LS messages + if(headerSubType == HST_LSREQUEST) { + byte[] gnAddress = new byte[8]; + System.arraycopy(message, 68, gnAddress, 0, 8); + byte[] mid = new byte[6]; + System.arraycopy(gnAddress, 2, mid, 0, 6); + if(Arrays.equals(mid, management.getLinkLayerAddress()) == true) { + // Send LS Reply + byte[] depv = new byte[20]; + System.arraycopy(message, 40, depv, 0, 20); + + Map params = new HashMap(); + params.put(GN_DEPV, depv); + params.put(GN_TYPE, HT_LS); + params.put(GN_SUBTYPE, HST_LSREPLY); + send(null, params); + } + } + else { + // we are not interested in LS replies so far. + } + } + else { + // Other messages + if(payloadLength > 0) { + byte[] payload = new byte[payloadLength]; + System.arraycopy(message, message.length - payloadLength, payload, 0, payloadLength); + lowerInfo.put(GN_NEXTHEADER, nextHeader); + super.receive(payload, lowerInfo); + } + } + } else { + if ((basicHdr[0] & 0x0f) == 0x02) { // Secured tag + int offset = basicHdr.length + 1; // Version fields + int signerInfoTypeIndex = 0; + // Extract Header length (IntX type) + if ((message[offset] & 0x80) == 0x80) { // Integer >= 128 + byte msb = message[offset]; // TODO Create a method decodeIntX + byte bit; + byte byteLen = 1; + do { + bit = (byte) ((byte) (msb << byteLen++) & 0x80); + } while (bit != 0x00); + // Set the IntX length + byte[] newBuf = ByteHelper.extract(message, offset, byteLen); + // Remove the length from the real integer value + newBuf[0] &= (byte)(Math.pow(2.0, 8 - byteLen + 1) - 1); + signerInfoTypeIndex = offset + byteLen; + offset += byteLen + ByteHelper.byteArrayToInt(newBuf); + } else { + signerInfoTypeIndex = offset + 1; + offset += message[offset] + 1; + } + offset += 1; // Skip Payload Type + // Extract Data Payload length (IntX type) + if ((message[offset] & 0x80) == 0x80) { // Integer >= 128 + byte msb = message[offset]; + byte bit; + byte byteLen = 1; + do { + bit = (byte) ((byte) (msb << byteLen++) & 0x80); + } while (bit != 0x00); + offset += byteLen; + } else { + offset +=1; + } + // Sanity check: Verify SignerInfo field + if ( + ((message[signerInfoTypeIndex] & 0x80) != 0x80) || // SignerInfo Type: certificate digest with ecdsap256 (1) + ( + (message[signerInfoTypeIndex + 1] != 0x01) && // SignerInfo Type: certificate digest with ecdsap256 (1) + (message[signerInfoTypeIndex + 1] != 0x02) // SignerInfo Type: certificate (2) + ) + ) { + // Drop it + return; + } + byte[] commonHdr = new byte[8]; + System.arraycopy(message, offset, commonHdr, 0, 8); +// System.out.println("GnLayer.receive: commonHdr: " + ByteHelper.byteArrayToString(commonHdr)); + + byte[] htHst = new byte[1]; + System.arraycopy(commonHdr, 1, htHst, 0, 1); + int headerType = (int)(htHst[0] >> 4); + int headerSubType = (int)(htHst[0] & 0x000000000F); + + byte[] pl = new byte[2]; + System.arraycopy(commonHdr, 4, pl , 0, 2); + int payloadLength = ByteHelper.byteArrayToInt(pl); + + if(headerType == HT_LS) { + // Process LS messages + if(headerSubType == HST_LSREQUEST) { + int sopvPos = offset + commonHdr.length + 3 + 8 + 3 * 4 + 2 * 2; + byte[] gnAddress = new byte[8]; + System.arraycopy(message, sopvPos, gnAddress, 0, 8); + byte[] mid = new byte[6]; + System.arraycopy(gnAddress, 2, mid, 0, 6); + if(Arrays.equals(mid, management.getLinkLayerAddress()) == true) { + // Send LS Reply + byte[] depv = new byte[20]; + System.arraycopy(message, sopvPos, depv, 0, 20); // FIXME Check indexes + + Map params = new HashMap(); + params.put(GN_DEPV, depv); + params.put(GN_TYPE, HT_LS); + params.put(GN_SUBTYPE, HST_LSREPLY); + send(null, params); + } + } else { + // we are not interested in LS replies so far. + } + } else { + // Other messages + if(payloadLength > 0) { + byte[] payload = new byte[payloadLength]; + System.arraycopy(message, message.length - payloadLength - 68, payload, 0, payloadLength); +// System.out.println("GnLayer.receive: payload: " + ByteHelper.byteArrayToString(payload)); + lowerInfo.put(GN_NEXTHEADER, nextHeader); +// System.out.println("GnLayer.receive: call super.receive: " + ByteHelper.byteArrayToString(payload)); + super.receive(payload, lowerInfo); + } + } + } + } + } // End of method receive + + /** * Builds encoded Basic Header * @return Encoded Basic Header */ private byte[] createBasicHeader() { // Version 4 bits // NextHeader 4 bits - byte[] versionNh = new byte[1]; + byte[] versionNh = new byte[1]; int nh = 1; versionNh[0] = (byte)(GN_VERSION << 4); versionNh[0] |= (byte)nh & 0x0F; + if (management.isSecuredModeSet()) { // Secure mode enabled + // Set nextHeader to secured + versionNh[0] &= 0xFE; + versionNh[0] |= 0x02; + } // Reserved 1 byte byte[] reserved = new byte[]{(byte)0x00}; @@ -363,175 +471,265 @@ public class GnLayer extends Layer implements Runnable, IEthernetSpecific { return ByteHelper.concat(versionNh, reserved, lifetime, rhl); } - - /** - * Builds encoded Common Header - * @param nextHeader Payload type - * @param ht Packet type - * @param hst Packet sub-type - * @param msgLength Length of payload - * @return Encoded Common Header - */ - private byte[] createCommonHeader(String nextHeader, int ht, int hst, int msgLength, int hoplimit) { - - // Version 4 bits - // NextHeader 4 bits - byte[] nhReserved = new byte[1]; - int nh = 0; - if(nextHeader != null) { - if(nextHeader.equals("BTP-A")) { - nh = 1; - } - else if(nextHeader.equals("BTP-B")) { - nh = 2; - } - else if(nextHeader.equals("IPv6")) { - nh = 3; - } - } - nhReserved[0] = (byte)(nh << 4); - - // HeaderType 4 bits - // HeaderSubType 4 bits - byte[] htHst = new byte[1]; - htHst[0] = (byte)(ht << 4); - htHst[0] |= (byte)hst & 0x0F; - - // Traffic Class 1 byte - byte[] tc = new byte[]{(byte)0x00}; - - // Flags 1 byte - byte[] flags = new byte[]{(byte)0x00}; - - // PayloadLength 2 bytes - byte[] pl = ByteHelper.intToByteArray(msgLength, 2); - - // Maximum HopLimit 1 byte - byte[] mhl = ByteHelper.intToByteArray(hoplimit, 1); - - // Reserved 1 byte + + /** + * Builds encoded Common Header + * @param nextHeader Payload type + * @param ht Packet type + * @param hst Packet sub-type + * @param msgLength Length of payload + * @return Encoded Common Header + */ + private byte[] createCommonHeader(String nextHeader, int ht, int hst, int msgLength, int hoplimit) { + + // Version 4 bits + // NextHeader 4 bits + byte[] nhReserved = new byte[1]; + int nh = 0; + if(nextHeader != null) { + if(nextHeader.equals("BTP-A")) { + nh = 1; + } + else if(nextHeader.equals("BTP-B")) { + nh = 2; + } + else if(nextHeader.equals("IPv6")) { + nh = 3; + } + } + nhReserved[0] = (byte)(nh << 4); + + // HeaderType 4 bits + // HeaderSubType 4 bits + byte[] htHst = new byte[1]; + htHst[0] = (byte)(ht << 4); + htHst[0] |= (byte)hst & 0x0F; + + // Traffic Class 1 byte + byte[] tc = new byte[]{(byte)0x00}; + + // Flags 1 byte + byte[] flags = new byte[]{(byte)0x00}; + + // PayloadLength 2 bytes + byte[] pl = ByteHelper.intToByteArray(msgLength, 2); + + // Maximum HopLimit 1 byte + byte[] mhl = ByteHelper.intToByteArray(hoplimit, 1); + + // Reserved 1 byte byte[] reserved = new byte[]{(byte)0x00}; - - return ByteHelper.concat(nhReserved, htHst, tc, flags, pl, mhl, reserved); - } - - /** - * Builds self GN_Address based on link-layer address - * @return Encoded GN_Address - */ - private byte[] createMyGnAddress() { - int ssc = 208; // France - byte[] flags = new byte[2]; - flags[0] = (byte)(1 << 7); // Manual address - flags[0] |= (byte)(9 << 3); // Ordinary RSU - flags[0] |= (byte)(1 << 2); // Private - flags[0] |= (byte)(ssc >> 10); // SSC - flags[1] = (byte)ssc; // SSC - byte[] mid = management.getLinkLayerAddress(); - return ByteHelper.concat(flags, mid); - } - - /** - * Builds self long position vector - * @return Encoded long position vector - */ - private byte[] createMyLpv() { - - byte[] gn = createMyGnAddress(); // 8 bytes - // Timestamp is 1s older than current time to avoid sending beacons coming from the future (time sync between nodes) - byte[] tst = ByteHelper.intToByteArray((int)((System.currentTimeMillis() - ITS_REF_TIME) % (long)Math.pow(2,32) - 1000), 4); - byte[] latitude = management.getLatitude(); - byte[] longitude = management.getLongitude(); - byte[] speed = ByteHelper.intToByteArray(0, 2); - byte[] heading = ByteHelper.intToByteArray(0, 2); - return ByteHelper.concat(gn, tst, latitude, longitude, speed, heading); - } - - /** - * Builds GeoUnicast extension header - * @param depv Destination position vector (short position vector) - * @return Encoded GeoUnicast extension header - */ - private byte[] createGeoUnicastHeader(byte[] depv) { - byte[] tsb = createTsbHeader(); - return ByteHelper.concat(tsb, depv); - } + + return ByteHelper.concat(nhReserved, htHst, tc, flags, pl, mhl, reserved); + } + + /** + * Builds self GN_Address based on link-layer address + * @return Encoded GN_Address + */ + private byte[] createMyGnAddress() { + int ssc = 208; // France + byte[] flags = new byte[2]; + flags[0] = (byte)(1 << 7); // Manual address + flags[0] |= (byte)(9 << 3); // Ordinary RSU + flags[0] |= (byte)(1 << 2); // Private + flags[0] |= (byte)(ssc >> 10); // SSC + flags[1] = (byte)ssc; // SSC + byte[] mid = management.getLinkLayerAddress(); + return ByteHelper.concat(flags, mid); + } + + /** + * Builds self long position vector + * @return Encoded long position vector + */ + private byte[] createMyLpv() { + + byte[] gn = createMyGnAddress(); // 8 bytes + // Timestamp is 1s older than current time to avoid sending beacons coming from the future (time sync between nodes) + byte[] tst = ByteHelper.intToByteArray((int)((System.currentTimeMillis() - ITS_REF_TIME) % (long)Math.pow(2,32) - 1000), 4); + byte[] latitude = management.getLatitude(); + byte[] longitude = management.getLongitude(); + byte[] speed = ByteHelper.intToByteArray(0, 2); + byte[] heading = ByteHelper.intToByteArray(0, 2); + return ByteHelper.concat(gn, tst, latitude, longitude, speed, heading); + } + + /** + * Builds GeoUnicast extension header + * @param depv Destination position vector (short position vector) + * @return Encoded GeoUnicast extension header + */ + private byte[] createGeoUnicastHeader(byte[] depv) { + byte[] tsb = createTsbHeader(); + return ByteHelper.concat(tsb, depv); + } - /** + /** * Builds SHB extension header * @return Encoded SHB extension header */ private byte[] createShbHeader() { byte[] sopv = createMyLpv(); byte[] reserved = ByteHelper.intToByteArray(0, 4); - return ByteHelper.concat(sopv, reserved); + return ByteHelper.concat(sopv, reserved); } - - /** - * Builds TSB extension header - * @return Encoded TSB extension header - */ - private byte[] createTsbHeader() { - byte[] sn = ByteHelper.intToByteArray(sequenceNumber++ , 2); - byte[] reserved = ByteHelper.intToByteArray(0, 2); - byte[] sopv = createMyLpv(); - return ByteHelper.concat(sn, reserved, sopv); - } - - /** - * Builds GeoBroadcast extension header - * @param geoAreaLatitude Destination GeoArea's latitude - * @param geoAreaLongitude Destination GeoArea's longitude - * @param distanceA Destination GeoArea's distance A - * @param distanceB Destination GeoArea's distance B - * @param angle Destination GeoArea's angle - * @return Encoded GeoBroadcast extension header - */ - private byte[] createGeoBroadcastHeader(long geoAreaLatitude, long geoAreaLongitude, int distanceA, int distanceB, int angle) { - byte[] tsb = createTsbHeader(); - byte[] lat = ByteHelper.longToByteArray(geoAreaLatitude & 0xffffffffL, 4); - byte[] lng = ByteHelper.longToByteArray(geoAreaLongitude & 0xffffffffL, 4); - byte[] distA = ByteHelper.intToByteArray(distanceA, 2); - byte[] distB = ByteHelper.intToByteArray(distanceB, 2); - byte[] ang = ByteHelper.intToByteArray(angle, 2); - byte[] reserved = ByteHelper.intToByteArray(0, 2); - return ByteHelper.concat(tsb, lat, lng, distA, distB, ang, reserved); - } - - /** - * Builds LS Request extension header - * @param gnAddress Target GN_Address - * @return Encoded LS Request extension header - */ - private byte[] createLsRequestHeader(byte[] gnAddress) { - byte[] tsb = createTsbHeader(); - return ByteHelper.concat(tsb, gnAddress); - } - - /** - * Builds LS Reply extension header - * @param depv Destination position vector (short position vector) - * @return Encoded LS Reply extension header - */ - private byte[] createLsReplyHeader(byte[] depv) { - byte[] tsb = createTsbHeader(); - return ByteHelper.concat(tsb, depv); - } - - /** + + /** + * Builds TSB extension header + * @return Encoded TSB extension header + */ + private byte[] createTsbHeader() { + byte[] sn = ByteHelper.intToByteArray(sequenceNumber++ , 2); + byte[] reserved = ByteHelper.intToByteArray(0, 2); + byte[] sopv = createMyLpv(); + return ByteHelper.concat(sn, reserved, sopv); + } + + /** + * Builds GeoBroadcast extension header + * @param geoAreaLatitude Destination GeoArea's latitude + * @param geoAreaLongitude Destination GeoArea's longitude + * @param distanceA Destination GeoArea's distance A + * @param distanceB Destination GeoArea's distance B + * @param angle Destination GeoArea's angle + * @return Encoded GeoBroadcast extension header + */ + private byte[] createGeoBroadcastHeader(long geoAreaLatitude, long geoAreaLongitude, int distanceA, int distanceB, int angle) { + byte[] tsb = createTsbHeader(); + byte[] lat = ByteHelper.longToByteArray(geoAreaLatitude & 0xffffffffL, 4); + byte[] lng = ByteHelper.longToByteArray(geoAreaLongitude & 0xffffffffL, 4); + byte[] distA = ByteHelper.intToByteArray(distanceA, 2); + byte[] distB = ByteHelper.intToByteArray(distanceB, 2); + byte[] ang = ByteHelper.intToByteArray(angle, 2); + byte[] reserved = ByteHelper.intToByteArray(0, 2); + return ByteHelper.concat(tsb, lat, lng, distA, distB, ang, reserved); + } + + /** + * Builds LS Request extension header + * @param gnAddress Target GN_Address + * @return Encoded LS Request extension header + */ + private byte[] createLsRequestHeader(byte[] gnAddress) { + byte[] tsb = createTsbHeader(); + return ByteHelper.concat(tsb, gnAddress); + } + + /** + * Builds LS Reply extension header + * @param depv Destination position vector (short position vector) + * @return Encoded LS Reply extension header + */ + private byte[] createLsReplyHeader(byte[] depv) { + byte[] tsb = createTsbHeader(); + return ByteHelper.concat(tsb, depv); + } + + private byte[] createSecuredMessage(final byte[] basicHdr, final byte[] commonHdr, final byte[] extHdr, final byte[] message) { + // SecuredMessage payload length + int payloadLength = commonHdr.length + extHdr.length + message.length; + + // Build the generation time value + long curtime = System.currentTimeMillis(); + byte[] generationTime = ByteHelper.longToByteArray((long)(curtime - 1072915200000L) * 1000L, Long.SIZE / Byte.SIZE); // In microseconds +// System.out.println("GnLayer.createSecuredMessage: generationTime=" + ByteHelper.byteArrayToString(generationTime)); + // Build the payload to be signed + byte[] headersField = ByteHelper.concat( + ByteHelper.concat( // SecuredMessage HeaderFields + new byte[] { + (byte)0x80, // signerInfo + (byte)0x01 // Certificate digest with ecdsap256 + }, + management.getAtCertificateDigest(), // Hashed8 + new byte[] { + (byte)0x00, // generationTime + }, + generationTime // Time64 value + ) + ); + if ((commonHdr[0] & 0xF0) == 0x00) { // Next header = Any + // Nothing to do + } else if ((commonHdr[0] & 0xF0) == 0x01) { // Next header = Btp-A + headersField = ByteHelper.concat( + headersField, + new byte[] { + (byte)0x05, // its-aid + (byte)0xC0, + (byte)0x40, + (byte)0x80 // 16512 = CAM + } + ); + } else if ((commonHdr[0] & 0xF0) == 0x02) { // Next header = Btp-B + headersField = ByteHelper.concat( + headersField, + new byte[] { + (byte)0x03 // GenerationLocation + }, + management.getLatitude(), // Latitude + management.getLongitude(), // Longitude + new byte[] { (byte)0x00, (byte)0x00 }, // Elevation + new byte[] { + (byte)0x05, // its-aid + (byte)0xC0, + (byte)0x40, + (byte)0x81 // 16513 = DENM + } + ); + } + byte[] toBeSignedData = ByteHelper.concat( + new byte[] { // SecuredMessage version + (byte)0x02 // version + }, + new byte[] { (byte)headersField.length }, // HeadersField length + headersField, // HeaderFields + new byte[] { // SecuredMessage Payloads + (byte)0x01, // Secured payload type: signed (1) + (byte)payloadLength, // Data payload length + }, + commonHdr, + extHdr, + message, // End of SecuredMessage Payloads + new byte[] { (byte)0x01 }, // Signature + new byte[] { (byte)0x43 } // Signature length + ); +// System.out.println("GnLayer.createSecuredMessage: toBeSignedData=" + ByteHelper.byteArrayToString(toBeSignedData)); + + byte[] toBeSent = null; + try { + // Calculate the hash + byte[] hash = CryptoLib.hashWithSha256(toBeSignedData); + // Signed the hash + byte[] signatureBytes = CryptoLib.signWithEcdsaNistp256WithSha256(hash, management.getSigningPrivateKey()); + // Add signature + toBeSent = ByteHelper.concat( + basicHdr, + toBeSignedData, + new byte[] { 0x01, 0x00, 0x02 }, // Signature header + ByteHelper.extract(signatureBytes, 2, signatureBytes.length - 2) + ); + } catch (Exception e) { + e.printStackTrace(); + } + +// System.out.println("GnLayer.createSecuredMessage: toBeSent=" + ByteHelper.byteArrayToString(toBeSent)); + return toBeSent; + } + + /** * Indicates whether the layer is still active. Setting this field to false will cause * the beaconning thread to stop its execution. */ - private boolean running; - - /** + private boolean running; + + /** * Beaconning thread instance. */ - private Thread beaconThread; - - /** - * Packet sequence number. Incremented after sending each unicast packet - */ - private int sequenceNumber; + private Thread beaconThread; + + /** + * Packet sequence number. Incremented after sending each unicast packet + */ + private int sequenceNumber; } diff --git a/javasrc/adapter/org/etsi/its/adapter/layers/LayerFactory.java b/javasrc/adapter/org/etsi/its/adapter/layers/LayerFactory.java index 80960b9d1..79fe65d5a 100644 --- a/javasrc/adapter/org/etsi/its/adapter/layers/LayerFactory.java +++ b/javasrc/adapter/org/etsi/its/adapter/layers/LayerFactory.java @@ -30,62 +30,63 @@ public class LayerFactory { /** * Unique instance of the factory */ - private static LayerFactory instance = new LayerFactory(); - - /** + private static LayerFactory instance = new LayerFactory(); + + /** * List of the registered layer types */ - protected Map> layers = new TreeMap>(); - - /** + protected Map> layers = new TreeMap>(); + + /** * Private constructor (Singleton pattern) */ - private LayerFactory() { - // Register the layers - layers.put("BTP", BtpLayer.class); - layers.put("GN", GnLayer.class); - layers.put("G5", G5Layer.class); - layers.put("ETH", EthernetLayer.class); - - layers.put("Loopback", LoopbackLayer.class); - layers.put("Debug", DebugLayer.class); - layers.put("CamSource", CamSourceLayer.class); - layers.put("DenmSource", DenmSourceLayer.class); - layers.put("GnSource", GnSourceLayer.class); - layers.put("BtpSource", BtpSourceLayer.class); - layers.put("Gn6Source", Gn6SourceLayer.class); - } + private LayerFactory() { + // Register the layers + layers.put("BTP", BtpLayer.class); + layers.put("GN", GnLayer.class); + layers.put("G5", G5Layer.class); + layers.put("ETH", EthernetLayer.class); + +// layers.put("Loopback", LoopbackLayer.class); +// layers.put("Debug", DebugLayer.class); +// layers.put("CamSource", CamSourceLayer.class); +// layers.put("DenmSource", DenmSourceLayer.class); +// layers.put("GnSource", GnSourceLayer.class); +// layers.put("BtpSource", BtpSourceLayer.class); +// layers.put("Gn6Source", Gn6SourceLayer.class); + } - /** + /** * Gets the unique factory instance * @return LayerFactory instance */ - public static LayerFactory getInstance(){ - return instance; - } + public static LayerFactory getInstance(){ + return instance; + } - /** + /** * Creates a port of the desired type * @param management Layer management instance * @param layerName Name of the layer * @param lowerStack Lower protocol stack * @return Protocol port instance */ - public Layer createLayer(IManagementLayers management, String layerName, Stack lowerStack) { - Layer layer = null; - Class[] ctorParams = {IManagementLayers.class, lowerStack.getClass()}; - - try { - Class cls = layers.get(layerName); - if (cls == null) { - throw new RuntimeException("No class registered under " + layerName); - } + public Layer createLayer(IManagementLayers management, String layerName, Stack lowerStack) { +// System.out.println(">>> LayerFactory.createLayer: " + layerName); + Layer layer = null; + Class[] ctorParams = {IManagementLayers.class, lowerStack.getClass()}; + + try { + Class cls = layers.get(layerName); + if (cls == null) { + throw new RuntimeException("No class registered under " + layerName); + } Constructor ctor = cls.getConstructor(ctorParams); layer = ctor.newInstance(management, lowerStack); } catch (Exception ex) { ex.printStackTrace(); } return layer; - } + } } diff --git a/javasrc/adapter/org/etsi/its/adapter/ports/AdapterControlPort.java b/javasrc/adapter/org/etsi/its/adapter/ports/AdapterControlPort.java index 4996b5b93..8bfc7422b 100644 --- a/javasrc/adapter/org/etsi/its/adapter/ports/AdapterControlPort.java +++ b/javasrc/adapter/org/etsi/its/adapter/ports/AdapterControlPort.java @@ -17,7 +17,7 @@ import org.etsi.its.adapter.Management; public class AdapterControlPort extends AdapterPort implements IPort, IObservable { - /* AdapterControl Primitives */ + /* AdapterControl Primitives */ private static final byte AcGnPrimitive = 0; private static final byte AcGn6Primitive = 1; @@ -33,6 +33,8 @@ public class AdapterControlPort extends AdapterPort implements IPort, IObservabl private static final byte AcStartBeaconingMultipleNeighbour = 4; private static final byte AcStopBeaconingMultipleNeighbour = 5; private static final byte AcGetLongPosVector = 6; + private static final byte AcEnableSecurity = 7; + private static final byte AcDisableSecurity = 8; /* GN Responses */ protected static final byte AcGnResponseFailure = 0; @@ -40,117 +42,123 @@ public class AdapterControlPort extends AdapterPort implements IPort, IObservabl protected static final byte AcTrue = 0x01; protected static final byte AcFalse = 0x01; - - /** - * Constructor - * @param portName Name of the port - * @param componentName Name of the component owning this port instance - */ - public AdapterControlPort(final String portName, final String componentName) { - super(portName, componentName); - } - - @Override - public boolean send(final byte[] message) { - - boolean result = true; - try { - // Decode non protocol part - switch(message[0]) { - case AcGnPrimitive: { - byte[] data = ByteHelper.extract(message, 2, message.length - 2); - switch (message[1]) { - case AcGetLongPosVector: - ProcessAcGetLongPosVector(data); - break; - case AcStartBeaconing: - Management.getInstance(getComponentName()).startBeaconing(data); - break; - case AcStopBeaconing: - Management.getInstance(getComponentName()).stopBeaconing(); - break; - case AcStartPassBeaconing: - ProcessAcStartPassBeaconing(data); - break; - case AcStopPassBeaconing: - Management.getInstance(getComponentName()).stopEnqueueingBeacons(); - break; - case AcStartBeaconingMultipleNeighbour: - // TODO - break; - case AcStopBeaconingMultipleNeighbour: - // TODO - break; - } - } - break; - case AcGn6Primitive: - /* FIXME - try { - byte[] buf = new byte[4096]; - DatagramSocket remoteAdapterSocket = new DatagramSocket(); - InetAddress remoteAdapterAddress = InetAddress.getByName(((CharstringValue)TERFactory.getInstance().getTaParameter("Gn6RemoteAdapterIp")).getString()); - int remoteAdapterPort = Integer.decode(((CharstringValue)TERFactory.getInstance().getTaParameter("Gn6RemoteAdapterPort")).getString()); - - DatagramPacket command = new DatagramPacket(new byte[] {CMD_IFACES}, 1, remoteAdapterAddress, remoteAdapterPort); - DatagramPacket response = new DatagramPacket(buf, buf.length); - - remoteAdapterSocket.send(command); - remoteAdapterSocket.receive(response); - - byte[] data = ByteHelper.extract(response.getData(), response.getOffset(), response.getLength()); - if(data[0] == RPL_IFACES) { - // enqueue response... - byte[] buffer = impl.Encode(TestAdapterMessageTypeEnum.AcGn6Response, ByteHelper.extract(data, 1, data.length - 1), new Date().getTime()); - setChanged(); - notifyObservers(new PortEvent(buffer, getPortName(), getComponentName())); - } - } catch (SocketException e) { - e.printStackTrace(); - } catch (UnknownHostException e) { - e.printStackTrace(); - } - */ - break; - } // End of 'switch' statement - - return result; - } catch (Exception e) { - e.printStackTrace(); - } - - return false; - } // End of method send - - /** - * Processes AcGetLongPosVector command - * @param data - */ - private void ProcessAcGetLongPosVector(final byte[] gnAddress) { - - new Thread(new Runnable() { + + /** + * Constructor + * @param portName Name of the port + * @param componentName Name of the component owning this port instance + */ + public AdapterControlPort(final String portName, final String componentName) { + super(portName, componentName); + } + + @Override + public boolean send(final byte[] message) { + + boolean result = true; + try { + // Decode non protocol part + switch(message[0]) { + case AcGnPrimitive: { + byte[] data = ByteHelper.extract(message, 2, message.length - 2); + switch (message[1]) { + case AcGetLongPosVector: + ProcessAcGetLongPosVector(data); + break; + case AcStartBeaconing: + Management.getInstance(getComponentName()).startBeaconing(data); + break; + case AcStopBeaconing: + Management.getInstance(getComponentName()).stopBeaconing(); + break; + case AcStartPassBeaconing: + ProcessAcStartPassBeaconing(data); + break; + case AcStopPassBeaconing: + Management.getInstance(getComponentName()).stopEnqueueingBeacons(); + break; + case AcStartBeaconingMultipleNeighbour: + // TODO + break; + case AcStopBeaconingMultipleNeighbour: + // TODO + break; + case AcEnableSecurity: + Management.getInstance(getComponentName()).setSecuredMode(data); + break; + case AcDisableSecurity: + Management.getInstance(getComponentName()).unsetSecuredMode(); + break; + } + } + break; + case AcGn6Primitive: + /* FIXME + try { + byte[] buf = new byte[4096]; + DatagramSocket remoteAdapterSocket = new DatagramSocket(); + InetAddress remoteAdapterAddress = InetAddress.getByName(((CharstringValue)TERFactory.getInstance().getTaParameter("Gn6RemoteAdapterIp")).getString()); + int remoteAdapterPort = Integer.decode(((CharstringValue)TERFactory.getInstance().getTaParameter("Gn6RemoteAdapterPort")).getString()); + + DatagramPacket command = new DatagramPacket(new byte[] {CMD_IFACES}, 1, remoteAdapterAddress, remoteAdapterPort); + DatagramPacket response = new DatagramPacket(buf, buf.length); + + remoteAdapterSocket.send(command); + remoteAdapterSocket.receive(response); + + byte[] data = ByteHelper.extract(response.getData(), response.getOffset(), response.getLength()); + if(data[0] == RPL_IFACES) { + // enqueue response... + byte[] buffer = impl.Encode(TestAdapterMessageTypeEnum.AcGn6Response, ByteHelper.extract(data, 1, data.length - 1), new Date().getTime()); + setChanged(); + notifyObservers(new PortEvent(buffer, getPortName(), getComponentName())); + } + } catch (SocketException e) { + e.printStackTrace(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + */ + break; + } // End of 'switch' statement + + return result; + } catch (Exception e) { + e.printStackTrace(); + } + + return false; + } // End of method send + + /** + * Processes AcGetLongPosVector command + * @param data + */ + private void ProcessAcGetLongPosVector(final byte[] gnAddress) { + + new Thread(new Runnable() { @Override public void run() { byte[] response = null; byte[] responseHdr = {(byte)AcGnResponse, (byte)0x00}; - byte[] longPosVector = Management.getInstance(getComponentName()).getLongPositionVector(gnAddress); - if((longPosVector == null) || (longPosVector.length == 0)) { + byte[] longPosVector = Management.getInstance(getComponentName()).getLongPositionVector(gnAddress); + if((longPosVector == null) || (longPosVector.length == 0)) { responseHdr[1] = (byte)AcGnResponseFailure; response = ByteHelper.concat(responseHdr, new byte[]{AcTrue}); - } - else { + } + else { responseHdr[1] = (byte)AcLongPosVector; response = ByteHelper.concat(responseHdr, longPosVector); - } - - setChanged(); - notifyObservers(new PortEvent(response, getPortName(), getComponentName())); + } + + setChanged(); + notifyObservers(new PortEvent(response, getPortName(), getComponentName())); } }).start(); - } + } - private void ProcessAcStartPassBeaconing(final byte[] beacon) { + private void ProcessAcStartPassBeaconing(final byte[] beacon) { byte[] response = {(byte)AcGnResponse, (byte)AcGnResponseFailure, (byte)AcFalse}; Management.getInstance(getComponentName()).startEnqueueingBeacons(beacon); @@ -159,9 +167,9 @@ public class AdapterControlPort extends AdapterPort implements IPort, IObservabl notifyObservers(new PortEvent(response, getPortName(), getComponentName())); } - @Override - public void dispose() { - //empty - } + @Override + public void dispose() { + //empty + } } // End of class AdapterControlPort diff --git a/javasrc/adapter/org/etsi/its/adapter/ports/GnPort.java b/javasrc/adapter/org/etsi/its/adapter/ports/GnPort.java index ec69940a6..e462842f8 100644 --- a/javasrc/adapter/org/etsi/its/adapter/ports/GnPort.java +++ b/javasrc/adapter/org/etsi/its/adapter/ports/GnPort.java @@ -13,58 +13,62 @@ import java.util.Map; import org.etsi.adapter.TERFactory; import org.etsi.common.ByteHelper; +import org.etsi.its.adapter.TlsHelper; import org.etsi.its.adapter.layers.EthernetLayer; import org.etsi.its.adapter.layers.IEthernetSpecific; import org.etsi.ttcn.tci.CharstringValue; +import de.fraunhofer.sit.c2x.CryptoLib; + /** * GeoNetworking port implementation (background thread) */ public class GnPort extends ProtocolPort implements Runnable, IEthernetSpecific { - /** - * GeoNetworking header type for beacon messages - */ - private static final int HT_BEACON = 1; - private static final int HT_TSB = 5; - private static final int HST_SHB = 0; - - /** + /** + * GeoNetworking header type for beacon messages + */ + private static final int HT_BEACON = 1; + private static final int HT_TSB = 5; + private static final int HST_SHB = 0; + + + /** * Constructor * @param portName Name of the port * @param componentName Name of the component owning this port instance * @param lowerStackDesc Description of the port's lower stack in the form "Layer/Layer/Layer/..." * @param linkLayerAddress Link-layer address to be used by this port as source address (null if not applicable) */ - public GnPort(String portName, String componentName, String lowerStackDesc, String linkLayerAddress) { - super(portName, componentName, lowerStackDesc, linkLayerAddress); - running = true; - management.registerGnPort(this); - } + public GnPort(String portName, String componentName, String lowerStackDesc, String linkLayerAddress) { + super(portName, componentName, lowerStackDesc, linkLayerAddress); + running = true; + management.registerGnPort(this); + } - /* (non-Javadoc) - * @see org.etsi.its.adapter.ports.IEthernetSpecific#getEthernetType() - */ - @Override - public short getEthernetType() { - + /* (non-Javadoc) + * @see org.etsi.its.adapter.ports.IEthernetSpecific#getEthernetType() + */ + @Override + public short getEthernetType() { + // Retrieve EthernetType value Integer iutEthernetTypeValue = Integer.decode(((CharstringValue)TERFactory.getInstance().getTaParameter("IutEthernetTypeValue")).getString()); return iutEthernetTypeValue.shortValue(); } - /** - * Starts beaconning - */ - public void startBeaconning() { - running = true; - if(beaconThread == null) { - beaconThread = new Thread(this); - beaconThread.start(); - } - } - - /** + /** + * Starts beaconning + */ + public void startBeaconning() { + running = true; + if(beaconThread == null) { + beaconThread = new Thread(this); + beaconThread.start(); + } + } + + /** * Stops beaconning */ public void stopBeaconning() { @@ -79,118 +83,421 @@ public class GnPort extends ProtocolPort implements Runnable, IEthernetSpecific } } - /** - * Thread function for sending periodic beacons - * @see java.lang.Runnable#run() - */ - @Override - public void run() { - byte[] beaconHeader = management.getGnBeacon(); - if(beaconHeader != null) { - long modulo = (long)Math.pow(2,32); - Map params = new HashMap(); - while(running) { - // Update timestamp. Timestamp is 1s older than current time to avoid sending beacons coming from the future (time sync between nodes) - byte[] tst = ByteHelper.intToByteArray((int)(((System.currentTimeMillis() - 1072915200000L) % modulo) - 3000), 4); - - System.arraycopy(tst, 0, beaconHeader, 20, 4); - send(beaconHeader, params); + /** + * Thread function for sending periodic beacons + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + byte[] beaconHeader = management.getGnBeacon(); + if(beaconHeader != null) { + long modulo = (long)Math.pow(2,32); + Map params = new HashMap(); + long triggerTime = System.currentTimeMillis(); + boolean sendDigest = false; + while(running) { + // Update timestamp. Timestamp is 1s older than current time to avoid sending beacons coming from the future (time sync between nodes) + long currentTime = System.currentTimeMillis(); + byte[] tst = ByteHelper.intToByteArray((int)(((currentTime - 1072915200000L) % modulo) - 3000), 4); + System.arraycopy(tst, 0, beaconHeader, 20, 4); + if (!management.isSecuredModeSet()) { // Secure mode disabled + send(beaconHeader, params); + } else { // Send a secured beacon + // Retrieve the secured data template + sendDigest = (boolean)((currentTime - triggerTime) < 1000); + byte[] securedBeaconHeader; + if (sendDigest) { + securedBeaconHeader = buildSecuredBeacon(beaconHeader, tst, currentTime, sendDigest); + } else { + securedBeaconHeader = buildSecuredBeacon(beaconHeader, tst, currentTime, sendDigest); + } + triggerTime = currentTime; + // Send the secured beacon +// System.out.println("GnPort: Call send " + ByteHelper.byteArrayToString(securedBeaconHeader)); + send(securedBeaconHeader, params); + } try { Thread.sleep(management.getGnBeaconInterval()); } catch (InterruptedException e) { // Do nothing, we do not care } - } - } - } - - /* (non-Javadoc) + } + } + } + + private byte[] buildSecuredBeacon(final byte[] p_beacon, byte[] p_tst, final long p_currentTime, final boolean p_sendDigest) { +// System.out.println("GnPort.buildSecuredBeacon (1): " + ByteHelper.byteArrayToString(p_beacon)); + + byte[] basicHeader = ByteHelper.extract(p_beacon, 0, 4); + basicHeader[0] &= 0xFE; + basicHeader[0] |= 0x02; // Secured mode + + // Update the beacon timestamp field + byte[] beacon = ByteHelper.concat( + ByteHelper.extract(p_beacon, 4, 16), // Extract Common Header + GN address + p_tst, // Update the timestamp field + ByteHelper.extract(p_beacon, 20, p_beacon.length - 4 - 20) // Add remaining bytes + ); +// System.out.println("GnPort.buildSecuredBeacon (2): " + ByteHelper.byteArrayToString(beacon)); + // Prepare the message to be signed + byte[] toBeSignedData = buildToBeSignedData(beacon, p_currentTime, p_sendDigest); +// System.out.println("GnPort.buildSecuredBeacon: toBeSignedData " + ByteHelper.byteArrayToString(toBeSignedData)); + // Sign the message + byte[] securedBeaconHeader = signSecuredMessage(toBeSignedData); + + // Return the complete message to be sent + return ByteHelper.concat(basicHeader, securedBeaconHeader); + } + + private byte[] buildToBeSignedData(final byte[] p_beacon, final long p_currentTime, final boolean p_sendDigest) { +// System.out.println("GnPort.buildToBeSignedData: " + ByteHelper.byteArrayToString(p_beacon)); + + // Build the SignerInfo field + byte[] signerInfo = null; + if (!p_sendDigest) { + signerInfo = ByteHelper.concat( + new byte[] { + (byte)0x80, // signerInfo + (byte)0x02 // Certificate + }, + management.getAtCertificate() // Certificate value + ); + } else { + signerInfo = ByteHelper.concat( + new byte[] { + (byte)0x80, // signerInfo + (byte)0x01 // Certificate digest with ecdsap256 + }, + management.getAtCertificateDigest() // Hashed8 + ); + } + + // Build the generation time value + byte[] generationTime = ByteHelper.longToByteArray((long)(p_currentTime - 1072915200000L) * 1000L, Long.SIZE / Byte.SIZE); // In microseconds +// System.out.println("GnPort.buildToBeSignedData: generationTime=" + ByteHelper.byteArrayToString(generationTime)); + byte[] headersField = ByteHelper.concat( + ByteHelper.concat( // SecuredMessage HeaderFields + signerInfo, // signerInfo + new byte[] { + (byte)0x00, // generationTime + }, + generationTime // Time64 value + ) + ); + byte[] headersFieldLength = TlsHelper.getInstance().size2tls(headersField.length); +// System.out.println("GnPort.buildToBeSignedData: headersField=" + ByteHelper.byteArrayToString(headersField)); + byte[] toBeSignedData = ByteHelper.concat( + new byte[] { // SecuredMessage version + (byte)0x02 // version + }, + headersFieldLength, // HeadersField length + headersField, // HeaderFields + new byte[] { // SecuredMessage Payloads + (byte)0x01, // Secured payload type: signed (1) + (byte)p_beacon.length // Data payload length + }, + p_beacon, // End of SecuredMessage Payloads + new byte[] { (byte)0x43 }, // Signature length + new byte[] { (byte)0x01 } // Signature + ); +// System.out.println("GnPort.buildToBeSignedData: toBeSignedData=" + ByteHelper.byteArrayToString(toBeSignedData)); + + return toBeSignedData; + } + + private byte[] signSecuredMessage(final byte[] p_toBeSignedData) { +// System.out.println("GnPort.signSecuredMessage: toBeSignedData: " + ByteHelper.byteArrayToString(p_toBeSignedData)); + + // Calculate the hash + byte[] hash = CryptoLib.hashWithSha256(p_toBeSignedData); +// System.out.println("GnPort.signSecuredMessage: hash=" + ByteHelper.byteArrayToString(hash)); + byte[] securedBeaconHeader = null; + // Signed the hash + byte[] signatureBytes; + try { + signatureBytes = CryptoLib.signWithEcdsaNistp256WithSha256(hash, management.getSigningPrivateKey()); +// System.out.println("GnPort.signSecuredMessage: signatureBytes=" + ByteHelper.byteArrayToString(signatureBytes)); + // Add signature + securedBeaconHeader = ByteHelper.concat( + p_toBeSignedData, + new byte[] { + (byte)0x00, // Public Key Alg: ecdsa nistp256 with sha256 (0) + (byte)0x02 // ECC Point Type: compressed lsb y-0 (2) + }, // Signature header + ByteHelper.extract(signatureBytes, 2, signatureBytes.length - 2) + ); + +// System.out.println("<<< GnPort.signSecuredMessage: sendBeacon: " + ByteHelper.byteArrayToString(securedBeaconHeader)); + return securedBeaconHeader; + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + /* (non-Javadoc) * @see org.etsi.its.adapter.ports.IPort#send(byte[]) */ @Override public boolean send(byte[] message) { HashMap params = new HashMap(); + ByteHelper.dump(">>> GnPort.send", message); byte[] destMacAddress = ByteHelper.extract(message, message.length - 6, 6); message = ByteHelper.extract(message, 0, message.length - 6); params.put(EthernetLayer.LINK_LAYER_DESTINATION, destMacAddress); + if (management.isSecuredModeSet()) { // Secure mode disabled + message = createSecuredMessage(message); + } ByteHelper.dump("GnPort.send", message); return send(message, params); } - - /* (non-Javadoc) - * @see org.etsi.its.adapter.ports.ProtocolPort#receive(byte[]) - */ - @Override - public void receive(byte[] message, Map lowerInfo) { + + /* (non-Javadoc) + * @see org.etsi.its.adapter.ports.ProtocolPort#receive(byte[]) + */ + @Override + public void receive(byte[] message, Map lowerInfo) { +// System.out.println(">>> GnPort.receive: " + ByteHelper.byteArrayToString(message)); + byte[] basicHdr = new byte[4]; System.arraycopy(message, 0, basicHdr, 0, 4); - byte[] commonHdr = new byte[8]; - System.arraycopy(message, 4, commonHdr, 0, 8); - byte[] htHst = new byte[1]; - System.arraycopy(commonHdr, 1, htHst, 0, 1); - int headerType = (int)(htHst[0] >> 4); - int headerSubType = (int)(htHst[0] & 0x000000000F); - - // Update LPV table - byte[] sopv = new byte[24]; - int sopvPos = 12; - if(headerType != HT_BEACON && !(headerType == HT_TSB && headerSubType == HST_SHB) ) { - sopvPos += 4; - } - System.arraycopy(message, sopvPos, sopv, 0, 24); - - byte[] gn = new byte[8]; - System.arraycopy(sopv, 0, gn, 0, 8); - byte[] mid = new byte[6]; - System.arraycopy(gn, 2, mid, 0, 6); - byte[] tst = new byte[4]; - System.arraycopy(sopv, 8, tst, 0, 4); - management.gnUpdateLocTable(mid, ByteHelper.byteArrayToInt(tst), sopv); - - // Filter beacons - byte [] beaconFilter = management.getGnEnqueueBeacon(); - if(headerType != HT_BEACON || beaconFilter != null) { - if(headerType == HT_BEACON) { - byte[] filterMid = new byte[6]; - System.arraycopy(beaconFilter, 2, filterMid, 0, 6); - if(java.util.Arrays.equals(mid, filterMid) == false) { - // Received beacon does not match filter - return; - } - } - // Encode with GN indication header - // Extract LINK_LAYER_DESTINATION - byte[] msgInd = ByteHelper.concat(message, (byte[])lowerInfo.get(EthernetLayer.LINK_LAYER_DESTINATION)); - super.receive(msgInd, lowerInfo); - } - } + int headerType = -1; + int headerSubType = -1; + byte[] sopv = new byte[24]; + if (!management.isSecuredModeSet()) { // Secure mode disabled + byte[] commonHdr = new byte[8]; + System.arraycopy(message, 4, commonHdr, 0, 8); + byte[] htHst = new byte[1]; + System.arraycopy(commonHdr, 1, htHst, 0, 1); + headerType = (int)(htHst[0] >> 4); + headerSubType = (int)(htHst[0] & 0x000000000F); + // Update LPV table + int sopvPos = 12; + if(headerType != HT_BEACON && !(headerType == HT_TSB && headerSubType == HST_SHB) ) { + sopvPos += 4; + } + System.arraycopy(message, sopvPos, sopv, 0, 24); + } else { + if ((basicHdr[0] & 0x0f) == 0x02) { // Secured tag + int offset = basicHdr.length + 1; // Skip version + int signerInfoTypeIndex = 0; + // Extract Header length (IntX type) + if ((message[offset] & 0x80) == 0x80) { // Integer >= 128 + byte msb = message[offset]; // TODO Create a method decodeIntX + byte bit; + byte byteLen = 1; + do { + bit = (byte) ((byte) (msb << byteLen++) & 0x80); + } while (bit != 0x00); + // Set the IntX length + byte[] newBuf = ByteHelper.extract(message, offset, byteLen); + // Remove the length from the real integer value + newBuf[0] &= (byte)(Math.pow(2.0, 8 - byteLen + 1) - 1); + signerInfoTypeIndex = offset + byteLen; + offset += byteLen + ByteHelper.byteArrayToInt(newBuf); + } else { + signerInfoTypeIndex = offset + 1; + offset += message[offset] + 1; + } + offset += 1; // Skip Payload Type + // Extract Data Payload length (IntX type) + if ((message[offset] & 0x80) == 0x80) { // Integer >= 128 + byte msb = message[offset]; + byte bit; + byte byteLen = 1; + do { + bit = (byte) ((byte) (msb << byteLen++) & 0x80); + } while (bit != 0x00); + offset += byteLen; + } else { + offset +=1; + } + // Sanity check: Verify SignerInfo field + if ( + ((message[signerInfoTypeIndex] & 0x80) != 0x80) || // SignerInfo Type: certificate digest with ecdsap256 (1) + ( + (message[signerInfoTypeIndex + 1] != 0x01) && // SignerInfo Type: certificate digest with ecdsap256 (1) + (message[signerInfoTypeIndex + 1] != 0x02) && // SignerInfo Type: certificate (2) + (message[signerInfoTypeIndex + 1] != 0x03) // SignerInfo Type: certificate chain (3) + ) + ) { + // Drop it + return; + } + byte[] commonHdr = new byte[8]; + System.arraycopy(message, offset, commonHdr, 0, 8); + byte[] htHst = new byte[1]; + System.arraycopy(commonHdr, 1, htHst, 0, 1); + headerType = (int)(htHst[0] >> 4); + headerSubType = (int)(htHst[0] & 0x000000000F); + // Update LPV table + int sopvPos = offset + commonHdr.length; + if(headerType != HT_BEACON && !(headerType == HT_TSB && headerSubType == HST_SHB) ) { + sopvPos += 4; + } + System.arraycopy(message, sopvPos, sopv, 0, 24); + } else { + // Drop it + return; + } + } + + byte[] gn = new byte[8]; + System.arraycopy(sopv, 0, gn, 0, 8); + byte[] mid = new byte[6]; + System.arraycopy(gn, 2, mid, 0, 6); + byte[] tst = new byte[4]; + System.arraycopy(sopv, 8, tst, 0, 4); + management.gnUpdateLocTable(mid, ByteHelper.byteArrayToInt(tst), sopv); + + // Filter beacons + byte [] beaconFilter = management.getGnEnqueueBeacon(); + if(headerType != HT_BEACON || beaconFilter != null) { + if(headerType == HT_BEACON) { + byte[] filterMid = new byte[6]; + System.arraycopy(beaconFilter, 2, filterMid, 0, 6); + if(java.util.Arrays.equals(mid, filterMid) == false) { + // Received beacon does not match filter + return; + } + } + // Encode with GN indication header + // Extract LINK_LAYER_DESTINATION + byte[] msgInd = ByteHelper.concat(message, (byte[])lowerInfo.get(EthernetLayer.LINK_LAYER_DESTINATION)); + super.receive(msgInd, lowerInfo); + } + } - /* (non-Javadoc) - * @see org.etsi.its.adapter.ports.ProtocolPort#dispose() - */ - @Override - public void dispose() { - if(running && beaconThread != null) { - running = false; - try { - beaconThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - super.dispose(); - } - - /** - * Indicates whether the port is still active. Setting this field to false will cause - * the beaconing thread to stop its execution. - */ - private volatile boolean running; - - /** - * Beaconing thread instance. - */ - private Thread beaconThread = null; + /* (non-Javadoc) + * @see org.etsi.its.adapter.ports.ProtocolPort#dispose() + */ + @Override + public void dispose() { + if(running && beaconThread != null) { + running = false; + try { + beaconThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + super.dispose(); + } + + private byte[] createSecuredMessage(final byte[] message) { +// System.out.println(">>> GnPort.createSecuredMessage:" + ByteHelper.byteArrayToString(message)); + + // Extract and update the basicHeader + byte[] basicHdr = ByteHelper.extract(message, 0, 4); + if ((basicHdr[0] & 0x02) == 0x02) { // Message already secured by the TE + return message; + } + // Set nextHeader to secured + basicHdr[0] &= 0xFE; + basicHdr[0] |= 0x02; +// System.out.println("GnPort.createSecuredMessage: basicHdr=" + ByteHelper.byteArrayToString(basicHdr)); + + // Extract and update the basicHeader + byte[] commonHdr = ByteHelper.extract(message, 4, 8); +// System.out.println("GnPort.createSecuredMessage: commonHdr=" + ByteHelper.byteArrayToString(commonHdr)); + + // Extract SecuredMessage payload + byte[] securedPayload = ByteHelper.extract(message, 4, message.length - 4); + int payloadLength = securedPayload.length; + + // Build the generation time value + long curtime = System.currentTimeMillis(); + byte[] generationTime = ByteHelper.longToByteArray((long)(curtime - 1072915200000L) * 1000L, Long.SIZE / Byte.SIZE); // In microseconds + // Build the payload to be signed + byte[] headersField = ByteHelper.concat( + ByteHelper.concat( // SecuredMessage HeaderFields + new byte[] { + (byte)0x80, // signerInfo + (byte)0x01 // Certificate digest with ecdsap256 + }, + management.getAtCertificateDigest(), // Hashed8 + new byte[] { + (byte)0x00, // generationTime + }, + generationTime // Time64 value + ) + ); + if ((commonHdr[0] & 0xF0) == 0x00) { // Next header = Any + // Nothing to do + } else if ((commonHdr[0] & 0xF0) == 0x10) { // Next header = Btp-A + headersField = ByteHelper.concat( + headersField, + new byte[] { + (byte)0x05, // its-aid + (byte)0xC0, + (byte)0x40, + (byte)0x80 // 16512 = CAM + } + ); + } else if ((commonHdr[0] & 0xF0) == 0x20) { // Next header = Btp-B + headersField = ByteHelper.concat( + headersField, + new byte[] { + (byte)0x03 // GenerationLocation + }, + management.getLatitude(), // Latitude + management.getLongitude(), // Longitude + new byte[] { (byte)0x00, (byte)0x00 }, // Elevation + new byte[] { + (byte)0x05, // its-aid + (byte)0xC0, + (byte)0x40, + (byte)0x81 // 16513 = DENM + } + ); + } + byte[] toBeSignedData = ByteHelper.concat( + new byte[] { // SecuredMessage version + (byte)0x02 // version + }, + new byte[] { (byte)headersField.length }, // HeadersField length + headersField, // HeaderFields + new byte[] { // SecuredMessage Payloads + (byte)0x01, // Secured payload type: signed (1) + (byte)payloadLength, // Data payload length + }, + securedPayload, + new byte[] { (byte)0x01 } // Signature + ); +// System.out.println("GnPort.createSecuredMessage: toBeSignedData=" + ByteHelper.byteArrayToString(toBeSignedData)); + + byte[] toBeSent = null; + try { + // Calculate the hash + byte[] hash = CryptoLib.hashWithSha256(toBeSignedData); + // Signed the hash + byte[] signatureBytes = CryptoLib.signWithEcdsaNistp256WithSha256(hash, management.getSigningPrivateKey()); + // Add signature + toBeSent = ByteHelper.concat( + basicHdr, + toBeSignedData, + new byte[] { 0x01, 0x00, 0x02 }, // Signature header + ByteHelper.extract(signatureBytes, 2, signatureBytes.length - 2) + ); + } catch (Exception e) { + e.printStackTrace(); + } + +// System.out.println("GnPort.createSecuredMessage: toBeSent=" + ByteHelper.byteArrayToString(toBeSent)); + return toBeSent; + } + + /** + * Indicates whether the port is still active. Setting this field to false will cause + * the beaconing thread to stop its execution. + */ + private volatile boolean running; + + /** + * Beaconing thread instance. + */ + private Thread beaconThread = null; } diff --git a/javasrc/adapter/org/etsi/its/adapter/ports/ProtocolPortFactory.java b/javasrc/adapter/org/etsi/its/adapter/ports/ProtocolPortFactory.java index f640d3999..ecb2461cd 100644 --- a/javasrc/adapter/org/etsi/its/adapter/ports/ProtocolPortFactory.java +++ b/javasrc/adapter/org/etsi/its/adapter/ports/ProtocolPortFactory.java @@ -17,50 +17,51 @@ import java.util.TreeMap; */ public class ProtocolPortFactory { - /** - * Unique instance of the factory - */ - private static ProtocolPortFactory instance = new ProtocolPortFactory(); - - /** - * List of the registered protocol port types - */ - protected Map> ports = new TreeMap>(); - - /** - * Private constructor (Singleton pattern) - */ - private ProtocolPortFactory() { - // Register the ports - Refer to TTCN-3 component LibIts_TestSystem.ItsSystem for ports name - ports.put("camPort", CamPort.class); - ports.put("denmPort", DenmPort.class); - ports.put("btpPort", BtpPort.class); - ports.put("geoNetworkingPort", GnPort.class); - ports.put("ipv6OverGeoNetworkingPort", Gn6Port.class); - ports.put("v2gPort", V2GPort.class); - } + /** + * Unique instance of the factory + */ + private static ProtocolPortFactory instance = new ProtocolPortFactory(); + + /** + * List of the registered protocol port types + */ + protected Map> ports = new TreeMap>(); + + /** + * Private constructor (Singleton pattern) + */ + private ProtocolPortFactory() { + // Register the ports - Refer to TTCN-3 component LibIts_TestSystem.ItsSystem for ports name + ports.put("camPort", CamPort.class); + ports.put("denmPort", DenmPort.class); + ports.put("btpPort", BtpPort.class); + ports.put("geoNetworkingPort", GnPort.class); + ports.put("ipv6OverGeoNetworkingPort", Gn6Port.class); + ports.put("v2gPort", V2GPort.class); + } - /** - * Gets the unique factory instance - * @return ProtocolPortFactory instance - */ - public static ProtocolPortFactory getInstance(){ - return instance; - } + /** + * Gets the unique factory instance + * @return ProtocolPortFactory instance + */ + public static ProtocolPortFactory getInstance(){ + return instance; + } - /** - * Creates a port of the desired type - * @param portName Name of the port - * @param componentName Name of the component owning the port instance - * @param lowerStackDesc Description of the lower protocol stack of the port in the form "Layer/Layer/Layer/..." - * @param linkLayerAddress Link-layer address to be used by this port as source address (null if not applicable) - * @return Protocol port instance - */ - public ProtocolPort createPort(String portName, String componentName, String lowerStackDesc, String linkLayerAddress) { - ProtocolPort port = null; - Class[] ctorParams = {portName.getClass(), componentName.getClass(), lowerStackDesc.getClass(), linkLayerAddress.getClass()}; - - try { + /** + * Creates a port of the desired type + * @param portName Name of the port + * @param componentName Name of the component owning the port instance + * @param lowerStackDesc Description of the lower protocol stack of the port in the form "Layer/Layer/Layer/..." + * @param linkLayerAddress Link-layer address to be used by this port as source address (null if not applicable) + * @return Protocol port instance + */ + public ProtocolPort createPort(String portName, String componentName, String lowerStackDesc, String linkLayerAddress) { +// System.out.println(">>> ProtocolPortFactory.createPort: " + portName + ", " + componentName + ", " + lowerStackDesc + ", " + linkLayerAddress); + ProtocolPort port = null; + Class[] ctorParams = {portName.getClass(), componentName.getClass(), lowerStackDesc.getClass(), linkLayerAddress.getClass()}; + + try { Class cls = ports.get(portName); if (cls == null) { @@ -74,6 +75,6 @@ public class ProtocolPortFactory { } return port; - } + } } \ No newline at end of file diff --git a/javasrc/certificatesio/org/etsi/certificates/CertificatesIOFactory.java b/javasrc/certificatesio/org/etsi/certificates/CertificatesIOFactory.java new file mode 100644 index 000000000..4aef21f51 --- /dev/null +++ b/javasrc/certificatesio/org/etsi/certificates/CertificatesIOFactory.java @@ -0,0 +1,32 @@ +package org.etsi.certificates; + +import org.etsi.certificates.io.CertificatesIO; +import org.etsi.certificates.io.ICertificatesIO; + +public class CertificatesIOFactory { + + /** + * The single instance of this class. + */ + private static CertificatesIOFactory _instance = new CertificatesIOFactory(); + + /** + * The single instance of the class CertificatesIO. + */ + private static ICertificatesIO _certIO = new CertificatesIO(); + + /** + * Accessor to the single instance of this class. + * @return The single instance of this class. + */ + public static ICertificatesIO getInstance() { + return _instance._certIO; + } + + /** + * Internal ctor (For invocation by subclass constructors, typically implicit) + */ + private CertificatesIOFactory() { + } + +} // End of class CertificatesIOFactory diff --git a/javasrc/certificatesio/org/etsi/certificates/Helpers.java b/javasrc/certificatesio/org/etsi/certificates/Helpers.java new file mode 100644 index 000000000..fe0518877 --- /dev/null +++ b/javasrc/certificatesio/org/etsi/certificates/Helpers.java @@ -0,0 +1,121 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id: + */ +package org.etsi.certificates; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public final class Helpers { + + + /** + * A single instance of this class + */ + private static Helpers instance; + + /** + * Synchronization object to provide single access to the instance + */ + private static Object _sync = new Object(); + + /** + * Provide the access to a single instance of this class + * @return A single instance of this class + */ + public static Helpers getInstance() { + if (instance == null) { + synchronized(_sync) { + if (instance == null) { + instance = new Helpers(); + } + } + } + + return instance; + } + + /** + * Internal ctor + */ + private Helpers() { + } + + /** + * Convert an array of strings to one string + * @param list string list + * @param separator 'separator' string between each element + * @return string list items concatenated into a string + */ + public String arrayToString(String[] list, String separator) { + StringBuffer result = new StringBuffer(); + if (list.length > 0) { + result.append(list[0]); + for (int i = 1; i < list.length; i++) { + result.append(separator); + result.append(list[i]); + } + } + + return result.toString(); + } + + /** + * Recursively walk a directory tree and return a List of all Files found; the List is sorted using File.compareTo(). + * @param startingDir is a valid directory, which can be read. + */ + public List getFileListing(File startingDir) throws FileNotFoundException { + validateDirectory(startingDir); + List result = getFileListingNoSort(startingDir); + Collections.sort(result); + return result; + } + + private List getFileListingNoSort(File startingDir) throws FileNotFoundException { + List result = new ArrayList(); + File[] filesAndDirs = startingDir.listFiles(); + List filesDirs = Arrays.asList(filesAndDirs); + + for (File file : filesDirs) { + if (file.isDirectory() && ((file.getName().indexOf(".svn") != -1) + || (file.getName().indexOf("._.DS_Store") != -1) + || (file.getName().indexOf(".DS_Store") != -1))) { // For debug purpose only + // Skip svn files + continue; + } + result.add(file); // always add, even if directory + if (!file.isFile()) { + //must be a directory + //recursive call! + List deeperList = getFileListingNoSort(file); + result.addAll(deeperList); + } + } + return result; + } + + /** + * Directory is valid if it exists, does not represent a file, and can be read. + */ + private void validateDirectory (File aDirectory) throws FileNotFoundException { + if (aDirectory == null) { + throw new IllegalArgumentException("Directory should not be null."); + } + if (!aDirectory.exists()) { + throw new FileNotFoundException("Directory does not exist: " + aDirectory); + } + if (!aDirectory.isDirectory()) { + throw new IllegalArgumentException("Is not a directory: " + aDirectory); + } + if (!aDirectory.canRead()) { + throw new IllegalArgumentException("Directory cannot be read: " + aDirectory); + } + } + +} // End of class Helpers diff --git a/javasrc/certificatesio/org/etsi/certificates/io/CertificatesIO.java b/javasrc/certificatesio/org/etsi/certificates/io/CertificatesIO.java new file mode 100644 index 000000000..ad1fbe6c6 --- /dev/null +++ b/javasrc/certificatesio/org/etsi/certificates/io/CertificatesIO.java @@ -0,0 +1,251 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.certificates.io; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.etsi.certificates.Helpers; +import org.etsi.common.ByteHelper; + +public class CertificatesIO implements ICertificatesIO { + + /** + * Regex pattern to extract signing private key + */ + private static final String SIGNING_PRIVATE_KEY_PATTERN = "^SigningPrivate key\\s*=\\s*([A-Fa-f0-9]+)$"; + + /** + * Regex pattern to extract encrypt private key + */ + private static final String ENCRYPT_PRIVATE_KEY_PATTERN = "^EncryptPrivate key\\s*=\\s*([A-Fa-f0-9]+)$"; + + /** + * Regex pattern to extract AA certificate + */ + private static final String CERT_AA_PATTERN = "^AUTHORIZATION_AUTHORITY.dump\\s*=\\s*([A-Fa-f0-9]+)$"; + + /** + * Regex pattern to extract AT certificate + */ + private static final String CERT_AT_PATTERN = "^AUTHORIZATION_TICKET.dump\\s*=\\s*([A-Fa-f0-9]+)$"; + + /** + * Regex compiler to extract signing private key + */ + private Pattern signingPrivateKeyPattern = Pattern.compile(SIGNING_PRIVATE_KEY_PATTERN, Pattern.MULTILINE); + + /** + * Regex compiler to extract encrypt private key + */ + private Pattern encryptPrivateKeyPattern = Pattern.compile(ENCRYPT_PRIVATE_KEY_PATTERN, Pattern.MULTILINE); + + /** + * Regex compiler to extract AA certificate + */ + private Pattern certAaPattern = Pattern.compile(CERT_AA_PATTERN, Pattern.MULTILINE); + + /** + * Regex compiler to extract AT certificate + */ + private Pattern certAtPattern = Pattern.compile(CERT_AT_PATTERN, Pattern.MULTILINE); + + /** + * Full path to access certificate files + */ + private String _fullPath; + + /** + * Memory cache for the certificates + */ + private Map _cachedCertificates; + + /** + * Memory cache for the signing private keys + */ + private Map _cachedSigningPrivateKey; + + /** + * Memory cache for the encrypt private keys + */ + private Map _cachedEncryptPrivateKey; + + /** + * Default constructor + */ + public CertificatesIO() { + _cachedCertificates = new ConcurrentHashMap(); + _cachedSigningPrivateKey = new ConcurrentHashMap(); + _cachedEncryptPrivateKey = new ConcurrentHashMap(); + } // End of Constructor + + /** + * @desc Load in memory cache the certificates available in the specified directory + * @param rootDirectory Root directory to access to the certificates identified by the certificate ID + * @param configId A configuration identifier + * @return true on success, false otherwise + */ + @Override + public boolean loadCertificates(final String rootDirectory, final String configId) { // E.g. , cfg01 + // Initialise the memory caches + _cachedCertificates.clear(); + _cachedSigningPrivateKey.clear(); + _cachedEncryptPrivateKey.clear(); + + // Build full path + if ((rootDirectory == null) || (rootDirectory.length() == 0)) { + _fullPath = System.getProperty("user.dir").replace("\\", "/"); + } else { + _fullPath = rootDirectory.replace("\\", "/"); + } + if (!_fullPath.endsWith("/")) { + _fullPath += "/"; + } + if ((configId != null) && (configId.length() != 0)) { + _fullPath += configId.replace('.', '/'); + } + _fullPath = _fullPath.toLowerCase(); + // Check the path + File path = new File(_fullPath); + if (!path.exists()) { + System.err.println("CertificatesIO.readCertificate: path '" + _fullPath + "' does not found"); + return false; + } + + return loadMemoryCache(path); // Load certificates and keys and return + } + + /** + * @desc Unload from memory cache the certificates available + * @return true on success, false otherwise + */ + @Override + public boolean unloadCertificates() { + _fullPath = null; + _cachedSigningPrivateKey.clear(); + _cachedEncryptPrivateKey.clear(); + + return true; + } + + /** + * @desc Read the specified certificate + * @param certificateId the certificate identifier + * @param certificate the expected certificate + * @return true on success, false otherwise + */ + @Override + public boolean readCertificate(final String key, final ByteArrayOutputStream certificate) { + // Sanity check + if (!_cachedCertificates.containsKey(key)) { + System.err.println("CertificatesIO.readCertificate: key '" + key + "' not found"); + return false; + } + + try { + certificate.write(_cachedCertificates.get(key)); + + return true; + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + + /** + * @desc Read the private keys for the specified certificate + * @param keysId the keys identifier + * @param signingPrivateKey the signing private key + * @param encryptPrivateKey the encrypt private key + * @return true on success, false otherwise + */ + @Override + public boolean readPrivateKeys(final String key, final ByteArrayOutputStream signingPrivateKey, final ByteArrayOutputStream encryptPrivateKey) { + // Sanity check + if (!_cachedSigningPrivateKey.containsKey(key) || !_cachedEncryptPrivateKey.containsKey(key)) { + System.err.println("CertificatesIO.readPrivateKeys: key '" + key + "' not found"); + return false; + } + + try { + signingPrivateKey.write(_cachedSigningPrivateKey.get(key)); + encryptPrivateKey.write(_cachedEncryptPrivateKey.get(key)); + + return true; + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + + private boolean loadMemoryCache(final File path) { // E.g. /ta_config_a.txt + // Retrieve the list of the files in the _fullpath + try { + List files = Helpers.getInstance().getFileListing(path); + // Create the memory cache + for (File file : files) { + addItem(file); + } // End of 'for' statement + + return true; + } catch (IOException e) { + e.printStackTrace(); + } + + return false; + } + + private void addItem(final File file) throws FileNotFoundException, IOException { + String key = file.getName().substring(0, file.getName().indexOf('.')).toUpperCase(); + if (!_cachedCertificates.containsKey(key)) { + FileInputStream fs = new FileInputStream(file.getCanonicalPath()); + byte bytes[] = new byte[(int) file.length()]; + fs.read(bytes); + String content = new String(bytes); + + // Extract SigningPrivateKey. Key identifier is key.PRIVATE_KEYS + // E.g. SigningPrivate key=68E45C8BBE0ABFA80188E62D082D7A1E5FD4D637D99A5826781280F3865B5819 + Matcher matcher = signingPrivateKeyPattern.matcher(content); + if (matcher.find()) { +// System.out.println("CertificatesIO.addItem: Add key '" + key + ".PRIVATE_KEYS" + "'"); + _cachedSigningPrivateKey.put(key + ".PRIVATE_KEYS", ByteHelper.hexStringToByteArray(matcher.group(1))); + } + // Extract EncryptPrivate. Key identifier is key.PRIVATE_KEYS + // E.g. EncryptPrivate key=00B65233550BE5A9866CF871D7712691CC47532A08C620D20579FB02BEFA3D1C5F + matcher = encryptPrivateKeyPattern.matcher(content); + if (matcher.find()) { +// System.out.println("CertificatesIO.addItem: Add key '" + key + ".PRIVATE_KEYS" + "'"); + _cachedEncryptPrivateKey.put(key + ".PRIVATE_KEYS", ByteHelper.hexStringToByteArray(matcher.group(1))); + } + + // Extract AUTHORIZATION_AUTHORITY.dump. Key identifier is key.AA_CERT + // E.g. AUTHORIZATION_AUTHORITY.dump=02015791FDC6CE82402F0210455453495F506C7567746573745F414180910000040E5F7F47D7A165E2DC403F1E8BAA14E6FF04ADE282CB22212056444CE0F193B01493338B6A8A5D36B2BE9CD3D1F5C708862BCD4539F9D99A0D9F7347066A92C001010004402A571AF5293651B3E2A931CEB1009805EB92E44288D08510E67BA629F14D61402A571AF5293651B3E2A931CEB1009805EB92E44288D08510E67BA629F14D6102202006C04080C040812401146757031A5617030303181DB9CF7C052616001DB9566E0526872A1D53F0D0052783500000A3EECD601A7D17D4C1EB4B8205EEFAE45E170872D49741941B5C9AEDEAA76E38938A67F98DCD46D390B9CF4C16AD324B9E6520565994790029A841E4C820BE4D + matcher = certAaPattern.matcher(content); + if (matcher.find()) { +// System.out.println("CertificatesIO.addItem: Add key '" + key + ".AA_CERT" + "'"); + _cachedCertificates.put(key + ".AA_CERT", ByteHelper.hexStringToByteArray(matcher.group(1))); + } + + // Extract AUTHORIZATION_TICKET.dump. Key identifier is key.AT_CERT + // E.g. AUTHORIZATION_TICKET.dump=0201CDF3567352CD8B4401008095000004DCBD7FBD344A653D42420350D3CB84E68C1E618ACC16FF4BA31D9D2913530A1ADED6F691D23476E779CCA54C63327F28E9E943929CF5C459DDA01E459279CAA0010100041D2EE0E362BF2798C5148BB198B2EB3718CB0B8714580A70A7161A5550D71F364FF1D5098A18E2B9CE142A17B5558A9E54438823D146CC24A372E7CE1761AF100220210AC040800100C0408101002401146757031A5617030303181DB9CF7C052616001DB9566E0526872A1D53F0D0052783500000AE35B36EA820B183AD0AD732656E2606A8C373C95DFA580FF4C049C66FEFD76F0B558C16932B4DC2BA0D52966AC3D56AC20E606DEDE63B625B4B80FDE1269335 + matcher = certAtPattern.matcher(content); + if (matcher.find()) { +// System.out.println("CertificatesIO.addItem: Add key '" + key + ".AT_CERT" + "'"); + _cachedCertificates.put(key + ".AT_CERT", ByteHelper.hexStringToByteArray(matcher.group(1))); + } + + } // else, ignore it + } + +} // End of class CertificatesIO diff --git a/javasrc/certificatesio/org/etsi/certificates/io/ICertificatesIO.java b/javasrc/certificatesio/org/etsi/certificates/io/ICertificatesIO.java new file mode 100644 index 000000000..1cc1ec5f1 --- /dev/null +++ b/javasrc/certificatesio/org/etsi/certificates/io/ICertificatesIO.java @@ -0,0 +1,48 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.certificates.io; + +import java.io.ByteArrayOutputStream; + +/** + * + * @desc Interface to load certificates/private keys from disk + * + */ +public interface ICertificatesIO { + + /** + * @desc Load in memory cache the certificates available in the specified directory + * @param rootDirectory Root directory to access to the certificates identified by the certificate ID + * @param configId A configuration identifier + * @return true on success, false otherwise + */ + boolean loadCertificates(final String rootDirectory, final String configId); + + /** + * @desc Unload from memory cache the certificates + * @return true on success, false otherwise + */ + boolean unloadCertificates(); + + /** + * @desc Read the specified certificate + * @param certificateId the certificate identifier + * @param certificate the expected certificate + * @return true on success, false otherwise + */ + boolean readCertificate(final String certificateId, final ByteArrayOutputStream certificate); + + /** + * @desc Read the private keys for the specified certificate + * @param keysId the keys identifier + * @param signingPrivateKey the signing private key + * @param encryptPrivateKey the encrypt private key + * @return true on success, false otherwise + */ + boolean readPrivateKeys(final String keysName, final ByteArrayOutputStream signingPrivateKey, final ByteArrayOutputStream encryptPrivateKey); + +} // End of interface ICertificatesIO diff --git a/javasrc/codec/org/etsi/codec/ITciCDWrapper.java b/javasrc/codec/org/etsi/codec/ITciCDWrapper.java index 9416f1325..be21a6279 100644 --- a/javasrc/codec/org/etsi/codec/ITciCDWrapper.java +++ b/javasrc/codec/org/etsi/codec/ITciCDWrapper.java @@ -1,5 +1,5 @@ /** - * @author STF 424_ITS_Test_Platform + * @author STF 424_ITS_Test_Platform * @version $URL$ * $Id$ */ @@ -7,9 +7,14 @@ package org.etsi.codec; import java.math.BigInteger; +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 org.etsi.ttcn.tci.Type; import org.etsi.ttcn.tci.Value; /** @@ -21,51 +26,110 @@ import org.etsi.ttcn.tci.Value; */ public interface ITciCDWrapper { - /** - * Constructs and returns a basic TTCN-3 integer type - * - * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getInteger - * @return An instance of Type representing a TTCN-3 integer type - */ - public IntegerValue getInteger(); + /** + * Constructs and returns a basic TTCN-3 integer type + * + * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getInteger + * @return An instance of Type representing a TTCN-3 integer type + */ + public IntegerValue setInteger(final Integer value); - /** - * Constructs and returns a basic TTCN-3 octet string type - * - * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getOctetstring - * @return An instance of Type representing a TTCN-3 octet string type - */ - public OctetstringValue getOctetstring(); + /** + * Constructs and returns a basic TTCN-3 big integer type + * + * @see ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getInteger + * @return An instance of Type representing a TTCN-3 integer type + */ + public IntegerValue setInteger(final BigInteger value); + + /** + * Constructs and returns a basic TTCN-3 big integer type + * + * @see ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getInteger + * @return An instance of Type representing a TTCN-3 integer type + */ + public void setInteger(final BigInteger value, IntegerValue setInt); - /** - * Constructs and returns a basic TTCN-3 float type - * - * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.3 getFloat - * @return An instance of Type representing a TTCN-3 float type - */ - public FloatValue getFloat(); + /** + * Constructs and returns a basic integer type + * + * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getInteger + * @return An instance of Type representing a TTCN-3 integer type + */ + public int getInteger(final IntegerValue iv); - /** - * Constructs and returns a basic TTCN-3 big integer type - * - * @see ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getInteger - * @return An instance of Type representing a TTCN-3 integer type - */ - IntegerValue getBigInteger(BigInteger bigInt); - - /** - * Constructs and returns a basic TTCN-3 float type - * - * @return An instance of Type representing a TTCN-3 float type - */ - public Value getUnionValue(final Type decodingHypothesis, final String variantName); - - /** - * Convert the specified type string into a Type object - * @param type The type in string format - * @return A Type object - */ - public Type getTypeForName(final String type); - - // FIXME To be continued + /** + * Constructs and returns a basic big integer type + * + * @see ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getInteger + * @return An instance of Type representing a TTCN-3 integer type + */ + public long/*TODO BigInteger*/ getBigInteger(final IntegerValue iv); + + /** + * Constructs and returns a basic TTCN-3 octet string type + * + * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getOctetstring + * @return An instance of Type representing a TTCN-3 octet string type + */ + public OctetstringValue getOctetstring(); + + /** + * Constructs and returns a basic TTCN-3 string type + * @return An instance of Type representing a TTCN-3 string type + */ + public CharstringValue getCharstringValue(); + + /** + * Constructs and returns a basic TTCN-3 float type + * + * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.3 getFloat + * @return An instance of Type representing a TTCN-3 float type + */ + public FloatValue getFloat(); + + /** + * Constructs and returns a basic TTCN-3 float type + * + * @return An instance of Type representing a TTCN-3 float type + */ + public Value getUnionValue(final Type decodingHypothesis, final String variantName); + + /** + * Constructs and returns a basic TTCN-3 float type + * + * @return An instance of Type representing a TTCN-3 float type + */ + public RecordValue getRecordValue(final String typeName); + + /** + * Constructs and returns a basic TTCN-3 float type + * + * @return An instance of Type representing a TTCN-3 float type + */ + public RecordOfValue getRecordOfValue(final String typeName); + + /** + * Constructs and returns a basic TTCN-3 boolean type + * + * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.4 getBoolean + * @return An instance of Type representing a TTCN-3 boolean type + */ + public BooleanValue getBoolean(); + + /** + * Constructs and returns a basic TTCN-3 enumerated type + * + * @return An instance of Type representing a TTCN-3 enumerated type + */ + public EnumeratedValue getEnumValue(String string); + + /** + * Convert the specified type string into a Type object + * @param type The type in string format + * @return A Type object + */ + public Type getTypeForName(final String type); + + // FIXME To be continued } // End of interface ITciCDWrapper diff --git a/javasrc/codec/org/etsi/ttcn/codec/CodecBuffer.java b/javasrc/codec/org/etsi/ttcn/codec/CodecBuffer.java index bf0832de2..f6bac2366 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/CodecBuffer.java +++ b/javasrc/codec/org/etsi/ttcn/codec/CodecBuffer.java @@ -131,10 +131,10 @@ public class CodecBuffer { * @see setMarkers() */ public void runCallbacks() { - System.out.println("Running callbacks..."); +// System.out.println("Running callbacks..."); for(Map.Entry entry : markers.entrySet()) { String key = entry.getKey(); - System.out.println("Running callback: " + key); +// System.out.println("Running callback: " + key); Marker marker = entry.getValue(); IMarkerCallback callback = marker.getCallback(); if(callback != null) { diff --git a/javasrc/codec/org/etsi/ttcn/codec/CodecFactory.java b/javasrc/codec/org/etsi/ttcn/codec/CodecFactory.java index 11af27c2e..44d512d5e 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/CodecFactory.java +++ b/javasrc/codec/org/etsi/ttcn/codec/CodecFactory.java @@ -11,9 +11,9 @@ import java.util.TreeMap; import org.etsi.ttcn.tci.TciCDProvided; import org.etsi.ttcn.tci.TciTypeClass; - import org.etsi.ttcn.codec.generic.Bitstring; import org.etsi.ttcn.codec.generic.Boolean; +import org.etsi.ttcn.codec.generic.Charstring; import org.etsi.ttcn.codec.generic.Octetstring; import org.etsi.ttcn.codec.generic.Integer; import org.etsi.ttcn.codec.generic.Set; @@ -33,9 +33,11 @@ public class CodecFactory { private CodecFactory() { codecs.put(TciTypeClass.BITSTRING + "//", Bitstring.class); codecs.put(TciTypeClass.OCTETSTRING + "//", Octetstring.class); + codecs.put(TciTypeClass.CHARSTRING + "//", Charstring.class); codecs.put(TciTypeClass.RECORD + "//", Record.class); codecs.put(TciTypeClass.SET + "//", Set.class); codecs.put(TciTypeClass.INTEGER + "//", Integer.class); + codecs.put(TciTypeClass.FLOAT + "//", org.etsi.ttcn.codec.generic.Float.class); codecs.put(TciTypeClass.UNION + "//", Union.class); codecs.put(TciTypeClass.ENUMERATED + "//", Enumerated.class); codecs.put(TciTypeClass.RECORD_OF + "//", RecordOf.class); @@ -61,7 +63,7 @@ public class CodecFactory { org.etsi.ttcn.codec.its.uppertester.Plugin.init(); org.etsi.ttcn.codec.its.geonetworking.Plugin.init(); org.etsi.ttcn.codec.its.btp.Plugin.init(); - + org.etsi.ttcn.codec.its.security.Plugin.init(); } } @@ -72,6 +74,7 @@ public class CodecFactory { return null; } +// System.out.println("getExternalCodec: Search external codec for " + encoding); codec = externalCodecs.get(encoding); if(codec != null) { System.out.print(String.format("%50s", encoding)); @@ -87,6 +90,7 @@ public class CodecFactory { Class cls = null; Class[] ctorParams = {MainCodec.class}; + System.out.println("getCodec: Search internal codec for " + classType + '/' + encoding + '/' + typeName); cls = codecs.get(classType + '/' + encoding + '/' + typeName); if(cls == null) { cls = codecs.get(classType + '/' + encoding + '/'); @@ -96,7 +100,7 @@ public class CodecFactory { } if(cls != null) { - System.out.println(" ==> " + cls.getName()); + System.out.println(" ==> " + cls.getName()); try { Constructor ctor = cls.getConstructor(ctorParams); return ctor.newInstance(mainCodec); @@ -111,6 +115,7 @@ public class CodecFactory { } public void setCodec(int classType, String encoding, String typeName, Class codec) { +// System.out.println("setCodec: add " + classType + "/" + encoding + "/" + typeName + "/" + codec); codecs.put(classType + '/' + encoding + '/' + typeName, codec); } diff --git a/javasrc/codec/org/etsi/ttcn/codec/ICodec.java b/javasrc/codec/org/etsi/ttcn/codec/ICodec.java index 7f69a9ab5..af9dcee31 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/ICodec.java +++ b/javasrc/codec/org/etsi/ttcn/codec/ICodec.java @@ -30,7 +30,10 @@ public class ICodec { try { Matcher matcher = PATTERN_VARIANT.matcher(variant); if(matcher.find()) { - return java.lang.Integer.parseInt(matcher.group(3)); + if (matcher.group(3) != null) + return java.lang.Integer.parseInt(matcher.group(3)); + else + return java.lang.Integer.parseInt(matcher.group(7)); } } catch(Exception e) { @@ -68,7 +71,7 @@ public class ICodec { return null; } - protected final static Pattern PATTERN_VARIANT = Pattern.compile("((\\w+)\\s+)?((\\d+))\\s+bit"); + protected final static Pattern PATTERN_VARIANT = Pattern.compile("((\\w+)\\s+)?((\\d+))\\s+bit|(\\w{0,1})(Int)(\\d+)"); protected final static Pattern PATTERN_ENCODING = Pattern.compile("length\\((\\d+)\\)"); protected MainCodec mainCodec; private int len; diff --git a/javasrc/codec/org/etsi/ttcn/codec/MainCodec.java b/javasrc/codec/org/etsi/ttcn/codec/MainCodec.java index 1691a8fe6..96f66d46c 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/MainCodec.java +++ b/javasrc/codec/org/etsi/ttcn/codec/MainCodec.java @@ -8,24 +8,29 @@ package org.etsi.ttcn.codec; import java.util.Map; import java.util.TreeMap; -import org.etsi.ttcn.tri.TriMessage; +import org.etsi.codec.ITciCDWrapper; +import org.etsi.ttcn.common.ByteHelper; import org.etsi.ttcn.tci.TciCDProvided; -import org.etsi.ttcn.tci.TciCDRequired; import org.etsi.ttcn.tci.Type; import org.etsi.ttcn.tci.Value; +import org.etsi.ttcn.tri.TriMessage; public class MainCodec extends ICodec { - public MainCodec(TciCDRequired cdReq) { + public MainCodec(ITciCDWrapper _cdReq) { super(null); - this.cdReq = cdReq; + this.cdReq = _cdReq; } public Value triDecode(TriMessage message, Type decodingHypothesis) { +// System.out.println("############################################################################################"); + return decode(new CodecBuffer(message.getEncodedMessage()), decodingHypothesis); } public TriMessage triEncode(Value value) { +// System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + CodecBuffer encoded = encode(value); encoded.runCallbacks(); return new TriMessageImpl(encoded.getBytes()); @@ -33,6 +38,8 @@ public class MainCodec extends ICodec { @Override public Value decode(CodecBuffer buf, Type decodingHypothesis) { + System.out.println(">>> MainCodec.decode: " + decodingHypothesis.getName()); + ByteHelper.dump(">>> MainCodec.decode: ", buf.getBytes()); CodecFactory cf = CodecFactory.getInstance(); TciCDProvided extCodec = cf.getExternalCodec(decodingHypothesis.getTypeEncoding()); @@ -42,7 +49,7 @@ public class MainCodec extends ICodec { } catch(Exception e) { return null; - } + } } else { ICodec codec = cf.getCodec( @@ -52,17 +59,22 @@ public class MainCodec extends ICodec { decodingHypothesis.getName() ); codec.preDecode(buf, decodingHypothesis); - return codec.decode(buf, decodingHypothesis); + + // TODO To be removed, for debug purpose only + Value decValue = codec.decode(buf, decodingHypothesis); + System.out.println("<<< MainCodec.decode: " + decValue); + return decValue; +// return codec.decode(buf, decodingHypothesis); } } @Override public CodecBuffer encode(Value value) { - + CodecFactory cf = CodecFactory.getInstance(); TciCDProvided extCodec = cf.getExternalCodec(value.getValueEncoding()); if(extCodec != null) { - return new CodecBuffer(extCodec.encode(value).getEncodedMessage()); + return new CodecBuffer(extCodec.encode(value).getEncodedMessage()); } else { ICodec codec = CodecFactory.getInstance().getCodec( @@ -77,31 +89,37 @@ public class MainCodec extends ICodec { preBuf.append(buf); buf = preBuf; } + + ByteHelper.dump("<<< MainCodec.encode: ", buf.getBytes()); return buf; } } - + public String getHint(String key) { +// System.out.println("getHint: " + key + ": " + hints.get(key)); return hints.get(key); } - + public void setHint(String key, String value) { +// System.out.println("setHint: " + key + ", " + value); hints.put(key, value); } - + public java.lang.Boolean getPresenceHint(String key) { +// System.out.println("getPresenceHint: " + key + ": " + presenceHints.get(key)); return presenceHints.get(key); } - + public void setPresenceHint(String key, java.lang.Boolean value) { +// System.out.println("setPresenceHint: " + key + ", " + value); presenceHints.put(key, value); } - - public TciCDRequired getTciCDRequired() { + + public ITciCDWrapper getTciCDRequired() { return cdReq; } - + protected Map hints = new TreeMap(); protected Map presenceHints = new TreeMap(); - protected TciCDRequired cdReq; + protected ITciCDWrapper cdReq; } diff --git a/javasrc/codec/org/etsi/ttcn/codec/generic/Bitstring.java b/javasrc/codec/org/etsi/ttcn/codec/generic/Bitstring.java index 5769f5c21..5ec901f12 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/generic/Bitstring.java +++ b/javasrc/codec/org/etsi/ttcn/codec/generic/Bitstring.java @@ -21,9 +21,11 @@ public class Bitstring extends ICodec { @Override public Value decode(CodecBuffer buf, Type decodingHypothesis) { - +// System.out.println(">>> Bitstring.decode: " + decodingHypothesis.getTypeEncoding()); + BitstringValue bv = (BitstringValue)decodingHypothesis.newInstance(); int lengthInBits = getEncodingLength(decodingHypothesis.getTypeEncoding()); +// System.out.println("Bitstring.decode: lengthInBits=" + lengthInBits); CodecBuffer value = new CodecBuffer(); value.setBits(buf.readBits(lengthInBits), lengthInBits); @@ -38,6 +40,7 @@ public class Bitstring extends ICodec { @Override public CodecBuffer encode(Value value) { +// System.out.println(">>> Bitstring.encode: " + value); BitstringValue bv = (BitstringValue)value; CodecBuffer encoded = new CodecBuffer(); diff --git a/javasrc/codec/org/etsi/ttcn/codec/generic/Charstring.java b/javasrc/codec/org/etsi/ttcn/codec/generic/Charstring.java index b128efb52..2fb05fad1 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/generic/Charstring.java +++ b/javasrc/codec/org/etsi/ttcn/codec/generic/Charstring.java @@ -47,7 +47,10 @@ public class Charstring extends ICodec { public CodecBuffer encode(Value value) { CharstringValue cv = (CharstringValue)value; - byte[] encoded = cv.getString().getBytes(); + byte[] encoded = new byte[] {}; + if (cv.getString() != null) { + encoded = cv.getString().getBytes(); + } return new CodecBuffer(encoded); } diff --git a/javasrc/codec/org/etsi/ttcn/codec/generic/Enumerated.java b/javasrc/codec/org/etsi/ttcn/codec/generic/Enumerated.java index 63ca1df6c..0f4349850 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/generic/Enumerated.java +++ b/javasrc/codec/org/etsi/ttcn/codec/generic/Enumerated.java @@ -21,6 +21,7 @@ public class Enumerated extends ICodec { @Override public Value decode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> Enumerated.decode: " + decodingHypothesis.getName()); EnumeratedValue ev = (EnumeratedValue)decodingHypothesis.newInstance(); int lengthInBits = 0; @@ -42,6 +43,7 @@ public class Enumerated extends ICodec { @Override public CodecBuffer encode(Value value) { +// System.out.println(">>> Enumerated.encode: " + value.getType().getName()); EnumeratedValue ev = (EnumeratedValue)value; int lengthInBits = 0; diff --git a/javasrc/codec/org/etsi/ttcn/codec/generic/Float.java b/javasrc/codec/org/etsi/ttcn/codec/generic/Float.java index 62c0b0808..40fc0ef98 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/generic/Float.java +++ b/javasrc/codec/org/etsi/ttcn/codec/generic/Float.java @@ -3,3 +3,44 @@ * @version $URL$ * $Id$ */ +package org.etsi.ttcn.codec.generic; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.ICodec; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.common.ByteHelper; +import org.etsi.ttcn.tci.FloatValue; +import org.etsi.ttcn.tci.Type; +import org.etsi.ttcn.tci.Value; + +public class Float extends ICodec { + + public Float(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + public Value decode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> Float.decode: " + decodingHypothesis.getName()); + + FloatValue fv = mainCodec.getTciCDRequired().getFloat(); + fv.setFloat(ByteHelper.byteArrayToFloat(buf.readBits(java.lang.Float.SIZE))); + + System.out.println("<<< Float.decode: " + fv.getFloat()); + return fv; + } + + @Override + public CodecBuffer encode(Value value) { +// System.out.println(">>> Float.encode: " + value.getType().getName()); + + FloatValue fv = (FloatValue)value; +// System.out.println("Float.encode: " + fv.getFloat()); + byte[] encoded = ByteHelper.floatToByteArray(fv.getFloat()); + CodecBuffer res = new CodecBuffer(); + res.setBits(encoded, encoded.length * Byte.SIZE); + + return res; + } + +} diff --git a/javasrc/codec/org/etsi/ttcn/codec/generic/Integer.java b/javasrc/codec/org/etsi/ttcn/codec/generic/Integer.java index 5a5bab109..acde3fc9a 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/generic/Integer.java +++ b/javasrc/codec/org/etsi/ttcn/codec/generic/Integer.java @@ -19,7 +19,7 @@ import org.etsi.ttcn.codec.CodecBuffer; public class Integer extends ICodec { - protected final static Pattern UNSIGNED_VARIANT = Pattern.compile("\\w*unsigned\\w*"); + protected final static Pattern UNSIGNED_VARIANT = Pattern.compile("\\w*unsigned\\w*|UInt"); public Integer(MainCodec mainCodec) { super(mainCodec); @@ -27,15 +27,20 @@ public class Integer extends ICodec { @Override public Value decode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> Integer.decode: " + decodingHypothesis.getName()); - IntegerValue iv = (IntegerValue)decodingHypothesis.newInstance(); + IntegerValue iv = null; int lengthInBits; byte[] value = null; // Get length String hint = mainCodec.getHint(decodingHypothesis.getName() + "Len"); if(hint == null) { - lengthInBits = getVariantBitLength(decodingHypothesis.getTypeEncodingVariant()); + if (decodingHypothesis.getTypeEncodingVariant() == null) { + lengthInBits = getVariantBitLength(decodingHypothesis.getName()); // TCT3 + } else { + lengthInBits = getVariantBitLength(decodingHypothesis.getTypeEncodingVariant()); + } } else { lengthInBits = java.lang.Integer.parseInt(hint); @@ -46,21 +51,28 @@ public class Integer extends ICodec { try { Matcher matcher = UNSIGNED_VARIANT.matcher(decodingHypothesis.getTypeEncodingVariant()); if(matcher.find()) { - // Unsigned integer - if(lengthInBits >= 32) { - iv.setBigInt(new BigInteger(1, value)); // /!\ ttwb specific + // Unsigned integer + if(lengthInBits >= java.lang.Integer.SIZE) { + iv = mainCodec.getTciCDRequired().setInteger(new BigInteger(1, value)); } else { - iv.setInt(ByteHelper.byteArrayToInt(value)); + iv = mainCodec.getTciCDRequired().setInteger(ByteHelper.byteArrayToInt(value)); } } else { // Signed integer - iv.setInt(ByteHelper.byteArrayToSignedInt(value, lengthInBits)); + iv = mainCodec.getTciCDRequired().setInteger(ByteHelper.byteArrayToSignedInt(value, lengthInBits)); } } catch(Exception e) { - // empty on purpose +// System.out.println("Integer.encode: " + decodingHypothesis.getTypeEncoding() + ", " + decodingHypothesis.getTypeEncodingVariant()); + // Assume unsigned integer + if(lengthInBits >= java.lang.Integer.SIZE) { + iv = mainCodec.getTciCDRequired().setInteger(new BigInteger(1, value)); + } + else { + iv = mainCodec.getTciCDRequired().setInteger(ByteHelper.byteArrayToInt(value)); + } // else, empty on purpose } return iv; @@ -68,6 +80,7 @@ public class Integer extends ICodec { @Override public CodecBuffer encode(Value value) { +// System.out.println(">>> Integer.encode: " + value.getType().getName()); IntegerValue iv = (IntegerValue)value; byte[] encoded = null; @@ -78,7 +91,13 @@ public class Integer extends ICodec { // Get length String hint = mainCodec.getHint(value.getType().getName() + "Len"); if(hint == null) { - lengthInBits = getVariantBitLength(value.getType().getTypeEncodingVariant()); +// System.out.println("Integer.encode: " + value.getValueEncodingVariant() + ", " + value.getValueEncoding()); +// System.out.println("Integer.encode: " + value.getType().getTypeEncodingVariant() + ", " + value.getType().getTypeEncoding()); + if (value.getType().getTypeEncodingVariant() != null) { + lengthInBits = getVariantBitLength(value.getType().getTypeEncodingVariant()); + } else { + lengthInBits = getVariantBitLength(value.getType().getName()); // TCT3 + } } else { lengthInBits = java.lang.Integer.parseInt(hint); @@ -87,11 +106,9 @@ public class Integer extends ICodec { // System.out.println(String.format("Integer.encode: length: %d", lengthInBytes)); if (lengthInBits > java.lang.Integer.SIZE) { - encoded = ByteHelper.longToByteArray(iv.getBigInt().longValue(), lengthInBytes); - res.setBits(encoded, lengthInBits); + encoded = ByteHelper.longToByteArray(mainCodec.getTciCDRequired().getBigInteger(iv), lengthInBytes); } else { - encoded = ByteHelper.intToByteArray(iv.getInt(), lengthInBytes); - res.setBits(encoded, lengthInBits); + encoded = ByteHelper.intToByteArray(mainCodec.getTciCDRequired().getInteger(iv), lengthInBytes); } res.setBits(encoded, lengthInBits); diff --git a/javasrc/codec/org/etsi/ttcn/codec/generic/Octetstring.java b/javasrc/codec/org/etsi/ttcn/codec/generic/Octetstring.java index 6c8164c97..acb960224 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/generic/Octetstring.java +++ b/javasrc/codec/org/etsi/ttcn/codec/generic/Octetstring.java @@ -20,6 +20,7 @@ public class Octetstring extends ICodec { @Override public Value decode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> Octetstring.decode: " + decodingHypothesis.getName()); OctetstringValue ov = (OctetstringValue)decodingHypothesis.newInstance(); byte[] value = null; @@ -29,6 +30,10 @@ public class Octetstring extends ICodec { String hint = mainCodec.getHint(decodingHypothesis.getName() + "Len"); if(hint == null) { lengthInBytes = getEncodingLength(decodingHypothesis.getTypeEncoding()); + if (lengthInBytes == 0) { +// System.out.println("Octetstring.decode: Decode full buffer"); + lengthInBytes = buf.getNbBytes(); + } } else { lengthInBytes = java.lang.Integer.parseInt(hint); @@ -45,6 +50,7 @@ public class Octetstring extends ICodec { @Override public CodecBuffer encode(Value value) { +// System.out.println(">>> Octetstring.encode: " + value.getType().getName()); OctetstringValue ov = (OctetstringValue)value; byte[] encoded = new byte[ov.getLength()]; diff --git a/javasrc/codec/org/etsi/ttcn/codec/generic/RecordOf.java b/javasrc/codec/org/etsi/ttcn/codec/generic/RecordOf.java index 51f5710df..d9c107585 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/generic/RecordOf.java +++ b/javasrc/codec/org/etsi/ttcn/codec/generic/RecordOf.java @@ -20,6 +20,7 @@ public class RecordOf extends ICodec { @Override public Value decode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> RecordOf.decode: " + decodingHypothesis.getName()); RecordOfValue rov = (RecordOfValue)decodingHypothesis.newInstance(); String lenHint = mainCodec.getHint(decodingHypothesis.getName() + "Len"); @@ -47,6 +48,7 @@ public class RecordOf extends ICodec { @Override public CodecBuffer encode(Value value) { +// System.out.println(">>> RecordOf.encode: " + value.getType().getName()); RecordOfValue rov = (RecordOfValue)value; CodecBuffer buf = new CodecBuffer(); diff --git a/javasrc/codec/org/etsi/ttcn/codec/generic/Union.java b/javasrc/codec/org/etsi/ttcn/codec/generic/Union.java index c41a217f2..04556c491 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/generic/Union.java +++ b/javasrc/codec/org/etsi/ttcn/codec/generic/Union.java @@ -25,11 +25,22 @@ public class Union extends ICodec { String variant = ""; variant = mainCodec.getHint(decodingHypothesis.getName()); +// System.out.println("Union: Looking for variant " + decodingHypothesis.getName() + "/" + variant); if(variant != null) { Value value = uv.getVariant(variant); - uv.setVariant(variant, mainCodec.decode(buf, value.getType())); - return uv; + if (value == null) { + value = mainCodec.getTciCDRequired().getUnionValue(decodingHypothesis, variant); + if (value != null) { +// System.out.println("Union (TCT3): " + value.getType().getName()); + uv.setVariant(variant, mainCodec.decode(buf, value.getType())); + return uv; + } + } else { +// System.out.println("Union (TTWB): " + value.getType().getName()); + uv.setVariant(variant, mainCodec.decode(buf, value.getType())); + return uv; + } } // no hint. Try all variants... @@ -39,7 +50,23 @@ public class Union extends ICodec { CodecBuffer variantBuf = buf.getBuffer(0, buf.getNbBits()); // Try to decode this variant - Value vv = mainCodec.decode(buf, uv.getVariant(variants[i]).getType()); + Value vv = null; + Value value = uv.getVariant(variants[i]); + if (value == null) { + value = uv.getVariant(mainCodec.getHint(variants[i])); + if (value == null) { + value = mainCodec.getTciCDRequired().getUnionValue(decodingHypothesis, mainCodec.getHint(variants[i])); + if (value != null) { +// System.out.println("Union (TCT3): " + value.getType().getName()); + vv = mainCodec.decode(buf, value.getType()); + } + } else { +// System.out.println("Union (TTWB): " + value.getType().getName()); + vv = mainCodec.decode(buf, value.getType()); + } + } else { + vv = mainCodec.decode(buf, value.getType()); + } if(vv != null) { buf.overwriteWith(variantBuf); uv.setVariant(variants[i], vv); @@ -55,7 +82,7 @@ public class Union extends ICodec { UnionValue uv = (UnionValue)value; CodecBuffer buf = new CodecBuffer(); - preEncode(buf, uv); + preEncode(buf, uv); CodecBuffer variantBuf = mainCodec.encode(uv.getVariant(uv.getPresentVariantName())); buf.append(variantBuf); diff --git a/javasrc/codec/org/etsi/ttcn/codec/ipv6/Ipv6ExtHdr.java b/javasrc/codec/org/etsi/ttcn/codec/ipv6/Ipv6ExtHdr.java index 68af068bb..de40cb9c1 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/ipv6/Ipv6ExtHdr.java +++ b/javasrc/codec/org/etsi/ttcn/codec/ipv6/Ipv6ExtHdr.java @@ -27,7 +27,8 @@ public class Ipv6ExtHdr extends Record { protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { if(fieldName.equals("hdrLen")) { - int len = ((IntegerValue)(rv.getField(fieldName))).getInt(); +// int len = ((IntegerValue)(rv.getField(fieldName))).getInteger(); TTWB iterface is getInt, TCI shall be getInteger + int len = mainCodec.getTciCDRequired().getInteger((IntegerValue)(rv.getField(fieldName))); mainCodec.setHint("Ipv6ExtHdrLen", Integer.toString(len)); } } diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/adapter/AcGnPrimitive.java b/javasrc/codec/org/etsi/ttcn/codec/its/adapter/AcGnPrimitive.java index 3dfebd64d..922dc5e5c 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/adapter/AcGnPrimitive.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/adapter/AcGnPrimitive.java @@ -52,6 +52,12 @@ public class AcGnPrimitive extends Union { case 6: primitive = "getLongPosVector"; break; + case 7: + primitive = "enableSecurity"; + break; + case 8: + primitive = "disableSecurity"; + break; } mainCodec.setHint(decodingHypothesis.getName(), primitive); @@ -87,6 +93,12 @@ public class AcGnPrimitive extends Union { else if(variant.equals("getLongPosVector")) { primitiveId = 6; } + else if(variant.equals("acEnableSecurity")) { + primitiveId = 7; + } + else if(variant.equals("acDisableSecurity")) { + primitiveId = 8; + } buf.appendBytes(ByteHelper.intToByteArray(primitiveId, 1)); } } diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/btp/BtpHeader.java b/javasrc/codec/org/etsi/ttcn/codec/its/btp/BtpHeader.java index 96a97b2bd..f8ccdf5d9 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/btp/BtpHeader.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/btp/BtpHeader.java @@ -14,8 +14,15 @@ public class BtpHeader extends Union { public BtpHeader(MainCodec mainCodec) { super(mainCodec); + setLengths(); } + private void setLengths() { + mainCodec.setHint("BtpPortIdLen", "16"); + mainCodec.setHint("BtpPortInfo", "16"); + } + + @Override protected void preDecode(CodecBuffer buf, Type decodingHypothesis) { diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/btp/BtpPacket.java b/javasrc/codec/org/etsi/ttcn/codec/its/btp/BtpPacket.java new file mode 100644 index 000000000..9bfd3cf3a --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/btp/BtpPacket.java @@ -0,0 +1,32 @@ +package org.etsi.ttcn.codec.its.btp; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class BtpPacket extends Record { + + public BtpPacket(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("BtpPortIdLen", "16"); + mainCodec.setHint("BtpPortInfoLen", "16"); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> BtpPacket.preDecodeField: " + fieldName + ", " + decodingHypothesis); + + if(fieldName.equals("payload")) { + if (buf.getNbBytes() == 0) { + mainCodec.setPresenceHint(fieldName, false); + } + } + } + +} diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/btp/DecodedBtpPayload.java b/javasrc/codec/org/etsi/ttcn/codec/its/btp/DecodedBtpPayload.java new file mode 100644 index 000000000..f8b5f7462 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/btp/DecodedBtpPayload.java @@ -0,0 +1,25 @@ +package org.etsi.ttcn.codec.its.btp; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Union; +import org.etsi.ttcn.tci.Type; + +public class DecodedBtpPayload extends Union { + + public DecodedBtpPayload(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("camPacket", "camPacket"); + mainCodec.setHint("denmPacket", "denmPacket"); + } + + @Override + protected void preDecode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> DecodedBtpPayload.preDecode: " + decodingHypothesis); + + } +} // End of class DecodedBtpPayload diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/btp/Payload.java b/javasrc/codec/org/etsi/ttcn/codec/its/btp/Payload.java index 7ce5a628d..281aa509b 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/btp/Payload.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/btp/Payload.java @@ -24,8 +24,12 @@ public class Payload extends Record { mainCodec.setHint(fieldName + "IgnoreErrorOnOptionalField", "true"); } else if(fieldName.equals("rawPayload")) { - buf.overwriteWith(rawBuffer); - mainCodec.setHint("BtpRawPayloadLen", Integer.toString(buf.getNbBytes())); + int pl = buf.getNbBytes(); + if (pl != 0) { + buf.overwriteWith(rawBuffer); + } else { + mainCodec.setPresenceHint(fieldName, false); + } } } diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/btp/Plugin.java b/javasrc/codec/org/etsi/ttcn/codec/its/btp/Plugin.java index 02571aa79..9bb2a34fb 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/btp/Plugin.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/btp/Plugin.java @@ -13,7 +13,10 @@ public class Plugin { public static void init() { CodecFactory cf = CodecFactory.getInstance(); - cf.setCodec(TciTypeClass.UNION, "LibItsBtp", "BtpHeader", BtpHeader.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsBtp", "BtpPacket", BtpPacket.class); cf.setCodec(TciTypeClass.RECORD, "LibItsBtp", "BtpPayload", Payload.class); + cf.setCodec(TciTypeClass.UNION, "LibItsBtp", "BtpHeader", BtpHeader.class); + cf.setCodec(TciTypeClass.UNION, "LibItsBtp", "DecodedBtpPayload", DecodedBtpPayload.class); + cf.setCodec(TciTypeClass.UNION, "LibItsBtp", "UtBtpEvent", UtBtpEvent.class); } } \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/btp/UtBtpEvent.java b/javasrc/codec/org/etsi/ttcn/codec/its/btp/UtBtpEvent.java new file mode 100644 index 000000000..5f8d29230 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/btp/UtBtpEvent.java @@ -0,0 +1,18 @@ +package org.etsi.ttcn.codec.its.btp; + +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Union; + +public class UtBtpEvent extends Union { + + public UtBtpEvent(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("BtpPortIdLen", "16"); + mainCodec.setHint("BtpPortInfoLen", "16"); + } + +} diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/BasicHeader.java b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/BasicHeader.java index 86b4586dc..380aa9475 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/BasicHeader.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/BasicHeader.java @@ -17,10 +17,32 @@ public class BasicHeader extends Record { public BasicHeader(MainCodec mainCodec) { super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("LtBaseLen", "2"); + mainCodec.setHint("BasicNextHeaderLen", "4"); + mainCodec.setHint("HeaderTypeLen", "4"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> BasicHeader.postEncodeField: " + fieldName); + + if(fieldName.equals("nextHeader")) { + mainCodec.setHint("GnNextHeader", Integer.toString(buf.getBytes(buf.getNbBytes() - 1, 1)[0])); + } + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> BasicHeader.preDecodeField: " + fieldName + ", " + decodingHypothesis); } @Override protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> BasicHeader.postDecodeField: " + fieldName + ", " + decodingHypothesis); if(fieldName.equals("nextHeader")) { int nh = ((EnumeratedValue)(rv.getField(fieldName))).getInt(); diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/CommonHeader.java b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/CommonHeader.java index 6ed9b5635..ff08131b3 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/CommonHeader.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/CommonHeader.java @@ -20,33 +20,52 @@ public class CommonHeader extends Record implements IMarkerCallback { public CommonHeader(MainCodec mainCodec) { super(mainCodec); + setLengths(); } + private void setLengths() { + mainCodec.setHint("HeaderTypeLen", "4"); + mainCodec.setHint("NextHeaderLen", "4"); + mainCodec.setHint("Bit8Len", "8"); + } + @Override protected void postEncodeField(String fieldName, CodecBuffer buf) { - - if(fieldName.equals("plLength")) { +// System.out.println(">>> CommonHeader.postEncodeField: " + fieldName); + + if(fieldName.equals("nextHeader")) { + int nh = buf.getBits(buf.getNbBits() - 4, 4)[0]; + mainCodec.setHint("NextHeader", Integer.toString(nh)); + } else if(fieldName.equals("plLength")) { buf.setMarker("plLength", 0, this); } } @Override - protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> CommonHeader.preDecodeField: " + fieldName + ", " + decodingHypothesis); + } + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> CommonHeader.postDecodeField: " + fieldName + ", " + decodingHypothesis); + if(fieldName.equals("nextHeader")) { int nh = ((EnumeratedValue)(rv.getField(fieldName))).getInt(); mainCodec.setHint("GnNextHeader", Integer.toString(nh)); } else if(fieldName.equals("plLength")) { - int pl = ((IntegerValue)(rv.getField(fieldName))).getInt(); +// int pl = ((IntegerValue)(rv.getField(fieldName))).getInteger(); TTWB iterface is getInt, TCI shall be getInteger + int pl = mainCodec.getTciCDRequired().getInteger((IntegerValue)(rv.getField(fieldName))); mainCodec.setHint("payloadLength", Integer.toString(pl)); } } @Override public void run(String markerName, CodecBuffer leftBuf, CodecBuffer rightBuf) { - +// System.out.println(">>> CommonHeader.run"); + if(markerName.equals("plLength")) { int pl = java.lang.Integer.parseInt(mainCodec.getHint("payloadLength")); CodecBuffer preserveRightBuf = rightBuf.getBuffer(16, rightBuf.getNbBits() - 16); diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GN_Address.java b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GN_Address.java new file mode 100644 index 000000000..6d8143b5d --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GN_Address.java @@ -0,0 +1,38 @@ +package org.etsi.ttcn.codec.its.geonetworking; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class GN_Address extends Record { + + public GN_Address(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("TypeOfAddressLen", "1"); + mainCodec.setHint("StationTypeLen", "5"); + mainCodec.setHint("Oct6Len", "6"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> GN_Address.postEncodeField: " + fieldName); + + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GN_Address.preDecodeField: " + fieldName + ", " + decodingHypothesis); + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GN_Address.postDecodeField: " + fieldName + ", " + decodingHypothesis); + + } +} diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GeoNetworkingPacket.java b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GeoNetworkingPacket.java index 3071f4fb1..ebe8e8019 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GeoNetworkingPacket.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GeoNetworkingPacket.java @@ -7,34 +7,114 @@ package org.etsi.ttcn.codec.its.geonetworking; import org.etsi.ttcn.codec.CodecBuffer; import org.etsi.ttcn.codec.MainCodec; -import org.etsi.ttcn.codec.generic.Union; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.common.ByteHelper; +import org.etsi.ttcn.tci.OctetstringValue; +import org.etsi.ttcn.tci.RecordValue; import org.etsi.ttcn.tci.Type; +import org.etsi.ttcn.tci.Value; -public class GeoNetworkingPacket extends Union { - +public class GeoNetworkingPacket extends Record { + + private boolean isSecuredMode = false; + + /** + * Used to decode the secured payload + */ + private Value packetValue; + public GeoNetworkingPacket(MainCodec mainCodec) { super(mainCodec); } + + @Override + public CodecBuffer encode(Value value) { +// System.out.println(">>> GeoNetworkingPacket.encode: " + value); + + return super.encode(value); + } + @Override + public CodecBuffer preEncode(Value value) { +// System.out.println(">>> GeoNetworkingPacket.preEncode: " + value); + + String gnNextHeader = mainCodec.getHint("GnNextHeader"); + isSecuredMode = (boolean)((gnNextHeader != null) && gnNextHeader.equals("32")); + + return new CodecBuffer(); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> GeoNetworkingPacket.postEncodeField: " + fieldName + ", " + isSecuredMode); + + if (isSecuredMode && fieldName.equals("packet")) { + // Ignore 'packet' encoding by reseting the CodecBuffer content + buf.overwriteWith(new CodecBuffer()); + } + } + + @Override + public Value decode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> GeoNetworkingPacket.decode: " + decodingHypothesis + ", " + isSecuredMode); + + packetValue = null; // Reset value + Value result = super.decode(buf, decodingHypothesis); // Normal decoding +// System.out.println("GeoNetworkingPacket.decode: Normal decoding=" + result); + if(isSecuredMode) { + // Override 'packet' field + RecordValue rv = (RecordValue) result; + rv.setField("packet", packetValue); + } + +// System.out.println("<<< GeoNetworkingPacket.decode: " + result); + return result; + } + @Override protected void preDecode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> GeoNetworkingPacket.preDecode: " + decodingHypothesis); + + String gnNextHeader = mainCodec.getHint("GnNextHeader"); + isSecuredMode = (boolean)((gnNextHeader != null) && gnNextHeader.equals("2")); +// System.out.println("GeoNetworkingPacket.preDecode: isSecuredMode=" + isSecuredMode); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GeoNetworkingPacket.preDecodeField: " + fieldName + ", " + decodingHypothesis + ", " + isSecuredMode); + + if(isSecuredMode) { + if (fieldName.equals("packet")) { + mainCodec.setPresenceHint(fieldName, false); // Consider this field as omitted to skip decoding + } else if(fieldName.equals("securedMsg")) { + // Nothing to do + } + } else if(fieldName.equals("securedMsg")) { + mainCodec.setPresenceHint(fieldName, false); + } + } - String nhHint = mainCodec.getHint("GnNextHeader"); - String variant = ""; - - if(nhHint != null) { - int nh = Integer.parseInt(nhHint); - switch(nh) { - case 1: - variant = "packet"; - break; - case 2: - variant = "securedPacket"; - break; - default: - variant = "packet"; + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GeoNetworkingPacket.postDecodeField: " + fieldName + ", " + rv); + + if(isSecuredMode) { + if(fieldName.equals("securedMsg")) { + RecordValue securedMsg = (RecordValue) rv.getField("securedMsg"); + RecordValue secPayload = (RecordValue) securedMsg.getField("payload_field"); + byte[] payload = new byte[]{}; + OctetstringValue ov = (OctetstringValue) secPayload.getField("data"); // See type record SecPayload + byte[] v = new byte[ov.getLength()]; + for (int j = 0; j < v.length; j++) { + v[j] = (byte) ov.getOctet(j); + } // End of 'for' statement + payload = ByteHelper.concat(payload, v); + + // Decode payload as GnNoSecured packet + packetValue = mainCodec.decode(new CodecBuffer(payload), rv.getField("packet").getType()); } } - mainCodec.setHint(decodingHypothesis.getName(), variant); } + } diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GeoNetworkingPdu.java b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GeoNetworkingPdu.java new file mode 100644 index 000000000..593aff7ae --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GeoNetworkingPdu.java @@ -0,0 +1,34 @@ +package org.etsi.ttcn.codec.its.geonetworking; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class GeoNetworkingPdu extends Record { + + public GeoNetworkingPdu(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> GeoNetworkingPdu.postEncodeField: " + fieldName); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GeoNetworkingPdu.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GeoNetworkingPdu.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class GeoNetworkingPdu diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GnIndReq.java b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GnIndReq.java index 49ba9170a..a136be53a 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GnIndReq.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GnIndReq.java @@ -10,6 +10,7 @@ import org.etsi.ttcn.codec.MainCodec; import org.etsi.ttcn.codec.generic.Record; import org.etsi.ttcn.tci.RecordValue; import org.etsi.ttcn.tci.Type; +import org.etsi.ttcn.tci.Value; public class GnIndReq extends Record { @@ -17,8 +18,19 @@ public class GnIndReq extends Record { super(mainCodec); } + @Override + protected void preDecode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> GnIndReq.preDecode: " + decodingHypothesis); + + int msgLen = buf.getNbBits() - 48; + + messageBuffer = buf.getBuffer(0, msgLen); + macBuffer = buf.getBuffer(msgLen, 48); + } + @Override protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GnIndReq.preDecodeField: " + fieldName + ", " + decodingHypothesis); if(fieldName.equals("macDestinationAddress")) { buf.overwriteWith(macBuffer); @@ -29,13 +41,18 @@ public class GnIndReq extends Record { } @Override - protected void preDecode(CodecBuffer buf, Type decodingHypothesis) { - int msgLen = buf.getNbBits() - 48; + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GnIndReq.postDecodeField: " + fieldName + ", " + decodingHypothesis); - messageBuffer = buf.getBuffer(0, msgLen); - macBuffer = buf.getBuffer(msgLen, 48); } + @Override + public CodecBuffer encode(Value value) { +// System.out.println("GnIndReq.encode: " + value); + + return super.encode(value); + } + private CodecBuffer messageBuffer = null; private CodecBuffer macBuffer = null; } diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GnNonSecuredPacket.java b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GnNonSecuredPacket.java index e8ca512eb..5f7152dc5 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GnNonSecuredPacket.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/GnNonSecuredPacket.java @@ -8,28 +8,67 @@ package org.etsi.ttcn.codec.its.geonetworking; import org.etsi.ttcn.codec.generic.Record; import org.etsi.ttcn.codec.MainCodec; import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.common.ByteHelper; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; import org.etsi.ttcn.tci.Value; public class GnNonSecuredPacket extends Record { - + + private static final byte c_protocolVersion = 0x02; + public GnNonSecuredPacket(MainCodec mainCodec) { super(mainCodec); } - + + @Override + protected void preDecode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> GnNonSecuredPacket.preDecode: " + decodingHypothesis); + + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GnNonSecuredPacket.preDecodeField: " + fieldName + ", " + decodingHypothesis); + + // FIXME Yann if payload length is 0, why payload is not set to omit? +// if(fieldName.equals("payload")) { +// if (buf.getNbBytes() == 0) { +// mainCodec.setPresenceHint(fieldName, false); +// } +// } + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GnNonSecuredPacket.postDecodeField: " + fieldName + ", " + decodingHypothesis); + + } + @Override protected void postEncodeField(String fieldName, CodecBuffer buf) { - +// System.out.println(">>> GnNonSecuredPacket.postEncodeField: " + fieldName); + if(fieldName.equals("payload")) { // Compute Payload's length and set a hint int length = buf.getNbBits() / 8; mainCodec.setHint("payloadLength", Integer.toString(length)); } } + + @Override + public CodecBuffer encode(Value value) { +// System.out.println(">>> GnNonSecuredPacket.encode: " + value); + + return super.encode(value); + } @Override public CodecBuffer preEncode(Value value) { +// System.out.println(">>> GnNonSecuredPacket.preEncode: " + value); mainCodec.setHint("payloadLength", Integer.toString(0)); return new CodecBuffer(); } + } \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/HeaderTST.java b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/HeaderTST.java index b21ffc14a..c481eea83 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/HeaderTST.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/HeaderTST.java @@ -18,6 +18,7 @@ public class HeaderTST extends Union { @Override protected void preDecode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> HeaderTST.preDecode: " + decodingHypothesis); int hdrType = 0x00FF & buf.getBits(0, 4)[0]; String variant = ""; diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/LongPosVector.java b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/LongPosVector.java new file mode 100644 index 000000000..10a309db7 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/LongPosVector.java @@ -0,0 +1,35 @@ +package org.etsi.ttcn.codec.its.geonetworking; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class LongPosVector extends Record { + + public LongPosVector(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("Bit1Len", "1"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> LongPosVector.postEncodeField: " + fieldName); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> LongPosVector.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> LongPosVector.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class LongPosVector diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/Payload.java b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/Payload.java index a1d6893f9..944564d15 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/Payload.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/Payload.java @@ -19,8 +19,9 @@ public class Payload extends Record { @Override protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> Payload.preDecode" + decodingHypothesis); - if(fieldName.equals("decodedPayload")) { + if(fieldName.equals("decodedPayload")) { String nhHint = mainCodec.getHint("GnNextHeader"); String variant = ""; @@ -52,6 +53,8 @@ public class Payload extends Record { @Override protected void preDecode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> Payload.preDecode: " + decodingHypothesis); + // Sanity check on pl int pl = java.lang.Integer.parseInt(mainCodec.getHint("payloadLength")); int remainingBytesForPayload = buf.getNbBytes(); diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/Plugin.java b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/Plugin.java index f1da5a65f..45c03341e 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/Plugin.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/Plugin.java @@ -14,8 +14,11 @@ public class Plugin { CodecFactory cf = CodecFactory.getInstance(); cf.setCodec(TciTypeClass.RECORD, "LibItsGeoNetworking", "BasicHeader", BasicHeader.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsGeoNetworking", "TrafficClass", TrafficClass.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsGeoNetworking", "LongPosVector", LongPosVector.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsGeoNetworking", "GN_Address", GN_Address.class); cf.setCodec(TciTypeClass.RECORD, "LibItsGeoNetworking", "CommonHeader", CommonHeader.class); - cf.setCodec(TciTypeClass.UNION, "LibItsGeoNetworking", "GeoNetworkingPacket", GeoNetworkingPacket.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsGeoNetworking", "GeoNetworkingPacket", GeoNetworkingPacket.class); cf.setCodec(TciTypeClass.RECORD, "LibItsGeoNetworking", "GnNonSecuredPacket", GnNonSecuredPacket.class); cf.setCodec(TciTypeClass.UNION, "LibItsGeoNetworking", "HeaderTST", HeaderTST.class); cf.setCodec(TciTypeClass.RECORD, "LibItsGeoNetworking", "Payload", Payload.class); diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/TrafficClass.java b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/TrafficClass.java new file mode 100644 index 000000000..405a64dfd --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/geonetworking/TrafficClass.java @@ -0,0 +1,38 @@ +package org.etsi.ttcn.codec.its.geonetworking; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class TrafficClass extends Record { + + public TrafficClass(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("SCFLen", "1"); + mainCodec.setHint("ChannelOffloadLen", "1"); + mainCodec.setHint("TcIdLen", "6"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> TrafficClass.postEncodeField: " + fieldName); + + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> TrafficClass.preDecodeField: " + fieldName + ", " + decodingHypothesis); + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> TrafficClass.postDecodeField: " + fieldName + ", " + decodingHypothesis); + + } +} diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/AcEnableSecurity.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/AcEnableSecurity.java new file mode 100644 index 000000000..6fb59bcf9 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/AcEnableSecurity.java @@ -0,0 +1,41 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.common.ByteHelper; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class AcEnableSecurity extends Record { + + public AcEnableSecurity(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> AcEnableSecurity.postEncodeField: " + fieldName); + + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> AcEnableSecurity.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("certificateId")) { + mainCodec.setHint(decodingHypothesis.getName() + "Len", String.valueOf(buf.getNbBytes())); + } + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> AcEnableSecurity.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class AcEnableSecurity diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/AesCcm.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/AesCcm.java new file mode 100644 index 000000000..8eb63f7c4 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/AesCcm.java @@ -0,0 +1,49 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class AesCcm extends Record { + + /** + * List of supported algorithms based on public key cryptography + */ + final byte e_ecdsa_nistp256_with_sha256 = 0x00; + /** + * List of supported algorithms based on public key cryptography + */ + final byte e_ecies_nistp2561 = 0x01; + + public AesCcm(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("SymmetricAlgorithmLen", "8"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> AesCcm.postEncodeField: " + fieldName); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> AesCcm.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> AesCcm.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class AesCcm diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/Certificate.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/Certificate.java new file mode 100644 index 000000000..8625a5c20 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/Certificate.java @@ -0,0 +1,35 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class Certificate extends Record { + + public Certificate(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> Certificate.postEncodeField: " + fieldName); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> Certificate.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> Certificate.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class Certificate \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/CertificateWithAlgo.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/CertificateWithAlgo.java new file mode 100644 index 000000000..b1e460f05 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/CertificateWithAlgo.java @@ -0,0 +1,35 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class CertificateWithAlgo extends Record { + + public CertificateWithAlgo(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> CertificateWithAlgo.postEncodeField: " + fieldName); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> CertificateWithAlgo.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> CertificateWithAlgo.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class CertificateWithAlgo diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/CircularRegion.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/CircularRegion.java new file mode 100644 index 000000000..83711c9c9 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/CircularRegion.java @@ -0,0 +1,17 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; + +public class CircularRegion extends Record { // TODO To be removed + + public CircularRegion(MainCodec mainCodec) { + super(mainCodec); + } + +} // End of class CircularRegion \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/Duration.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/Duration.java new file mode 100644 index 000000000..7d550f563 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/Duration.java @@ -0,0 +1,40 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class Duration extends Record { + + public Duration(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("Bit3Len", "3"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> Duration.postEncodeField: " + fieldName); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> Duration.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> Duration.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class Duration \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/EccPoint.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/EccPoint.java new file mode 100644 index 000000000..3b16007ba --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/EccPoint.java @@ -0,0 +1,96 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.common.ByteHelper; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class EccPoint extends Record { + + final byte c_x_coordinate_only = 0x00; /** Only the x coordinate is encoded */ + final byte c_compressed_lsb_y_0 = 0x02; /** The point is compressed and y's least significant bit is zero */ + final byte c_compressed_lsb_y_1 = 0x03; /** The point is compressed and y's least significant bit is one */ + final byte c_uncompressed = 0x04; /** The y coordinate is encoded in the field y */ + + public EccPoint(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("EccPointTypeLen", "8"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> EccPoint.postEncodeField: " + fieldName); + + if (fieldName.equals("type_")) { + // Store EccPointType value + mainCodec.setHint("EccPointType", Integer.toString(ByteHelper.byteArrayToInt(buf.getBytes(0, buf.getNbBytes())))); + } else if (fieldName.equals("x") || fieldName.equals("y")) { + // TODO Store first the octetstring length as specified in Draft ETSI TS 103 097 V1.1.14 Clause 4.2 + int type = Integer.parseInt(mainCodec.getHint("EccPointType")); + // TODO Check when octetsting length should be added +// if (type != c_uncompressed) { // Do not add length because of it is fixed to 32 +// CodecBuffer bufLen = new CodecBuffer(TlsHelper.getInstance().size2tls(buf.getNbBytes())); +// bufLen.append(buf); +// buf.overwriteWith(bufLen); +// } + } + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> EccPoint.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("type_")) { + byte type = buf.getBytes(0, 1)[0]; + // Store EccPointType value + mainCodec.setHint("EccPointType", Integer.toString(type)); + switch (type) { + case c_x_coordinate_only: + mainCodec.setPresenceHint("y", false); + break; + case c_compressed_lsb_y_0: + case c_compressed_lsb_y_1: + mainCodec.setPresenceHint("y", false); + break; + case c_uncompressed: + mainCodec.setPresenceHint("y", true); + mainCodec.setHint("EccPointContainer", "y"); // Set variant + break; + } // End of 'switch' statement + } else if (fieldName.equals("x")) { + int type = Integer.parseInt(mainCodec.getHint("EccPointType")); + int len = 32; + // TODO Check when octetsting length should be added +// if (type != c_uncompressed) { +// len = (int) TlsHelper.getInstance().tls2size(buf); +// } + mainCodec.setHint("octetstringLen", Integer.toString(len)); + } else if ((fieldName.equals("y") && mainCodec.getPresenceHint("y") == true)) { + int type = Integer.parseInt(mainCodec.getHint("EccPointType")); + int len = 32; + // TODO Check when octetsting length should be added +// if (type != c_uncompressed) { +// len = (int) TlsHelper.getInstance().tls2size(buf); +// } + mainCodec.setHint("octetstringLen", Integer.toString(len)); + mainCodec.setHint("EccPointContainer.yLen", Integer.toString(len)); // TCT3 Decoding EciesEncryptedKey, type became EccPointContainer.y + } + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> EccPoint.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class EccPoint diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/EcdsaSignature.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/EcdsaSignature.java new file mode 100644 index 000000000..f58d53399 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/EcdsaSignature.java @@ -0,0 +1,69 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +/** + * @desc Codec for ECDSA based signature + * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.9 EcdsaSignature + */ +public class EcdsaSignature extends Record { + + final byte c_uncompressed = 0x04; /** The y coordinate is encoded in the field y */ + + /** + * Constructor + * @param mainCodec MainCodec reference + */ + public EcdsaSignature(MainCodec mainCodec) { + super(mainCodec); + } + + /** + * @desc Set the variant according to the EcdsaSignature type + * @see See Draft ETSI TS 103 097 V1.1.14 Clause 4.2.9 EcdsaSignature + */ + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> EcdsaSignature.postEncodeField: " + fieldName); + + if (fieldName.equals("s")) { + int type = Integer.parseInt(mainCodec.getHint("EccPointType")); + // TODO Store first the octetstring length as specified in Draft ETSI TS 103 097 V1.1.14 Clause 4.2 +// if (type != c_uncompressed) { // Do not add length because of it is fixed to 32 +// CodecBuffer bufLen = new CodecBuffer(TlsHelper.getInstance().size2tls(buf.getNbBytes())); +// bufLen.append(buf); +// buf.overwriteWith(bufLen); +// } + } + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> EcdsaSignature.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("s")) { + int type = Integer.parseInt(mainCodec.getHint("EccPointType")); + int len = 32; + // TODO Store first the octetstring length as specified in Draft ETSI TS 103 097 V1.1.14 Clause 4.2 +// if (type != c_uncompressed) { +// len = (int) TlsHelper.getInstance().tls2size(buf); +// } + mainCodec.setHint("octetstringLen", Integer.toString(len)); + } + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> EcdsaSignature.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class EcdsaSignature \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/EciesEncryptedKey.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/EciesEncryptedKey.java new file mode 100644 index 000000000..0369be9a6 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/EciesEncryptedKey.java @@ -0,0 +1,62 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class EciesEncryptedKey extends Record { + + final byte c_aes_128_ccm = 0x00; /** Symmetric key cryptography algorithm AES-CCM as specified in NIST SP 800-38C */ + + public EciesEncryptedKey(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("Oct16Len", "16"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> EciesEncryptedKey.postEncodeField: " + fieldName); + + if (fieldName.equals("c")) { + int type = Integer.parseInt(mainCodec.getHint("SymmetricAlgorithm")); + if (type != c_aes_128_ccm) { // Do not add length because of it is fixed to 32 + CodecBuffer bufLen = new CodecBuffer(TlsHelper.getInstance().size2tls(buf.getNbBytes())); + bufLen.append(buf); + buf.overwriteWith(bufLen); + } + } + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> EciesEncryptedKey.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("c")) { + int type = Integer.parseInt(mainCodec.getHint("SymmetricAlgorithm")); + int len = 32; + if (type != c_aes_128_ccm) { + len = (int) TlsHelper.getInstance().tls2size(buf); + } + mainCodec.setHint("octetstringLen", Integer.toString(len)); + } else if (fieldName.equals("t")) { + mainCodec.setHint("octetstringLen", "20"); + } + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> EciesEncryptedKey.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class EciesEncryptedKey \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/EncryptionParameters.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/EncryptionParameters.java new file mode 100644 index 000000000..921a747ba --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/EncryptionParameters.java @@ -0,0 +1,56 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class EncryptionParameters extends Record { + + final byte c_aes_128_ccm = 0x00; /** Symmetric key cryptography algorithm AES-CCM as specified in NIST SP 800-38C */ + + public EncryptionParameters(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("SymmetricAlgorithmLen", "8"); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> EncryptionParameters.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + if (fieldName.equals("symm_algorithm")) { + byte type_ = buf.getBytes(0, 1)[0]; + mainCodec.setHint("SymmetricAlgorithm", String.valueOf(type_)); + switch (type_) { + case (byte)c_aes_128_ccm: + mainCodec.setHint("EncryptionParametersContainer", "nonce"); // Set variant + break; + default: + mainCodec.setHint("EncryptionParametersContainer", "params"); // Set variant + } // End of 'switch' statement + } else { + if (mainCodec.getHint("EncryptionParametersContainer").equals("nonce")) { + mainCodec.setHint("octetstringLen", "12"); + mainCodec.setHint("EncryptionParametersContainer.nonceLen", "12"); // TCT3 Decoding HeaderFieldContainer.enc_params, the type nonce became EncryptionParametersContainer.nonce + } else { + int len = buf.readBits(Byte.SIZE)[0]; // field_sizeLen is 1 bytes + mainCodec.setHint("EncryptionParametersContainer.paramsLen", Integer.toString(len)); + } + } + } + +} // End of class EncryptionParameters \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/EncryptionParametersContainer.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/EncryptionParametersContainer.java new file mode 100644 index 000000000..4a80b6ef2 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/EncryptionParametersContainer.java @@ -0,0 +1,34 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Union; +import org.etsi.ttcn.tci.OctetstringValue; +import org.etsi.ttcn.tci.UnionValue; + +public class EncryptionParametersContainer extends Union { + + public EncryptionParametersContainer(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("Oct12Len", "12"); + } + + @Override + protected void preEncode(CodecBuffer buf, UnionValue uv) { +// System.out.println(">>> EncryptionParametersContainer.preEncode: " + uv.getType().getName() + ", " + uv.getPresentVariantName()); + + if (uv.getPresentVariantName().equals("params")) { + buf.appendBytes(new byte[] { (byte)((OctetstringValue)(uv.getVariant(uv.getPresentVariantName()))).getLength() } ); + } + } + +} // End of class EncryptionParametersContainer diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/GeographicRegion.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/GeographicRegion.java new file mode 100644 index 000000000..e0076375c --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/GeographicRegion.java @@ -0,0 +1,71 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class GeographicRegion extends Record { + + final byte c_none = 0x00; + final byte c_circle = 0x01; + final byte c_rectangle = 0x02; + final byte c_polygon = 0x03; + final byte c_id = 0x04; + + /** + * Constructor + * @param mainCodec MainCodec reference + */ + public GeographicRegion(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + /** + * @desc Predefined field lengths + */ + private void setLengths() { + mainCodec.setHint("RegionTypeLen", "8"); + } + + /** + * @desc Set the variant according to the GeographicRegion type + * @see See Draft ETSI TS 103 097 V1.1.14 Clause 5.7 TrailerFieldType + */ + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GeographicRegion.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + if (fieldName.equals("region_type")) { + byte type_ = buf.getBytes(0, 1)[0]; + mainCodec.setPresenceHint("region", true); + switch (type_) { + case (byte)c_circle: + mainCodec.setHint("GeographicRegionContainer", "circular_region"); // Set variant + break; + case (byte)c_rectangle: + mainCodec.setHint("GeographicRegionContainer", "rectangular_region"); // Set variant + break; + case (byte)c_polygon: + mainCodec.setHint("GeographicRegionContainer", "polygonal_region"); // Set variant + break; + case (byte)c_id: + mainCodec.setHint("GeographicRegionContainer", "id_region"); // Set variant + break; + case (byte)c_none: + mainCodec.setPresenceHint("region", false); + break; + default: + mainCodec.setHint("GeographicRegionContainer", "other_region"); // Set variant + break; + } // End of 'switch' statement + } + } + +} // End of class GeographicRegion \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/GeographicRegionContainer.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/GeographicRegionContainer.java new file mode 100644 index 000000000..a4be62251 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/GeographicRegionContainer.java @@ -0,0 +1,30 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Union; +import org.etsi.ttcn.tci.OctetstringValue; +import org.etsi.ttcn.tci.UnionValue; + +public class GeographicRegionContainer extends Union { + + public GeographicRegionContainer(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void preEncode(CodecBuffer buf, UnionValue uv) { +// System.out.println(">>> GeographicRegionContainer.preEncode: " + uv.getType().getName() + ", " + uv.getPresentVariantName()); + + if (uv.getPresentVariantName().equals("other_region")) { + // FIXME Check for opaque length encoding depending of the length value : <= 127 or > 127 + buf.appendBytes(new byte[] { (byte)((OctetstringValue)(uv.getVariant(uv.getPresentVariantName()))).getLength() } ); + } + } + +} // End of class GeographicRegionContainer diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/GnSecurityInd.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/GnSecurityInd.java new file mode 100644 index 000000000..82639a90a --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/GnSecurityInd.java @@ -0,0 +1,35 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class GnSecurityInd extends Record { + + public GnSecurityInd(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GnSecurityInd.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + + @Override + protected void preDecode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> GnSecurityInd.postDecode: " + decodingHypothesis.getName()); + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> GnSecurityInd.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class GnSecurityInd diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/HashedId3.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/HashedId3.java new file mode 100644 index 000000000..fa114bb94 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/HashedId3.java @@ -0,0 +1,29 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Octetstring; +import org.etsi.ttcn.tci.Type; + +public class HashedId3 extends Octetstring { + + public HashedId3(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("HashedId3Len", "3"); + } + + @Override + protected void preDecode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> HashedId3.preDecode: " + decodingHypothesis.getName()); + } + +} // End of class HashedId3 \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/HashedId8.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/HashedId8.java new file mode 100644 index 000000000..f4e5bb0a9 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/HashedId8.java @@ -0,0 +1,22 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Octetstring; + +public class HashedId8 extends Octetstring { + + public HashedId8(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("HashedId8Len", "8"); + } + +} // End of class HashedId8 \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/HeaderField.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/HeaderField.java new file mode 100644 index 000000000..f054e794c --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/HeaderField.java @@ -0,0 +1,92 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +/** + * @desc Information of interest to the security layer + * @see Draft ETSI TS 103 097 V1.1.14 Clause 5.4 HeaderField + */ +public class HeaderField extends Record { + + final byte c_generation_time = 0x00; /** A timestamp of type Time64 */ + final byte c_generation_time_with_standard_deviation= 0x01; /** A timestamp of type Time64WithStandardDeviation */ + final byte c_expiration = 0x02; /** The point in time the validity of this message expires */ + final byte c_generation_location = 0x03; /** The location where this message was created */ + final byte c_request_unrecognized_certificate = 0x04; /** A request for certificates */ + final byte c_its_aid = 0x05; /** Its AID valued used to identify CAM/DENM secured messages */ + final byte c_signer_info = (byte)0x80; /** Information about the message's signer */ + final byte c_encryption_parameters = (byte)0x81; /** Information specific for certain recipients */ + final byte c_recipient_info = (byte)0x82; /** Additional parameters necessary for encryption purposes */ + + /** + * Constructor + * @param mainCodec MainCodec reference + */ + public HeaderField(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + /** + * @desc Predefined field lengths + */ + private void setLengths() { + mainCodec.setHint("HeaderFieldTypeLen", "8"); + mainCodec.setHint("Oct2Len", "2"); + } + + /** + * @desc Set the variant according to the HeaderField type + * @see See Draft ETSI TS 103 097 V1.1.14 Clause 5.5 HeaderFieldType + */ + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> HeaderField.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + if (fieldName.equals("type_")) { + byte type_ = buf.getBytes(0, 1)[0]; + switch (type_) { + case (byte)c_generation_time: + mainCodec.setHint("HeaderFieldContainer", "generation_time"); // Set variant + break; + case (byte)c_generation_time_with_standard_deviation: + mainCodec.setHint("HeaderFieldContainer", "generation_time_with_standard_deviation"); // Set variant + break; + case (byte)c_expiration: + mainCodec.setHint("HeaderFieldContainer", "expiry_time"); // Set variant + break; + case (byte)c_generation_location: + mainCodec.setHint("HeaderFieldContainer", "generation_location"); // Set variant + break; + case (byte)c_request_unrecognized_certificate: + mainCodec.setHint("HeaderFieldContainer", "digests"); // Set variant + mainCodec.setHint("HashedId3Len", "3"); // FIXME TCT3 returns 12/length(3)/HashedId3 instead of 12/LibItsSecurity/HashedId3 + break; + case (byte)c_its_aid: + mainCodec.setHint("HeaderFieldContainer", "its_aid"); // Set variant + break; + case (byte)c_signer_info: + mainCodec.setHint("HeaderFieldContainer", "signer"); // Set variant + break; + case (byte)c_encryption_parameters: + mainCodec.setHint("HeaderFieldContainer", "enc_params"); // Set variant + break; + case (byte)c_recipient_info: + mainCodec.setHint("HeaderFieldContainer", "recipients"); // Set variant + break; + default: + mainCodec.setHint("HeaderFieldContainer", "other_header"); // Set variant + break; + } // End of 'switch' statement + } + } + +} // End of class HeaderField \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/HeaderFieldContainer.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/HeaderFieldContainer.java new file mode 100644 index 000000000..d52d4a54f --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/HeaderFieldContainer.java @@ -0,0 +1,39 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Union; +import org.etsi.ttcn.tci.OctetstringValue; +import org.etsi.ttcn.tci.Type; +import org.etsi.ttcn.tci.UnionValue; + +/** + * @desc Container for the information of interest to the security layer + * @see Draft ETSI TS 103 097 V1.1.14 Clause 5.4 HeaderField + */ +public class HeaderFieldContainer extends Union { + + public HeaderFieldContainer(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void preEncode(CodecBuffer buf, UnionValue uv) { +// System.out.println(">>> HeaderFieldContainer.preEncode: " + uv.getType().getName() + ", " + uv.getPresentVariantName()); + + if (uv.getPresentVariantName().equals("other_header")) { + buf.appendBytes(new byte[] { (byte)((OctetstringValue)(uv.getVariant(uv.getPresentVariantName()))).getLength() } ); + } + } + + @Override + protected void preDecode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> HeaderFieldContainer.preDecode: " + decodingHypothesis.getName()); + } + +} // End of class HeaderFieldContainer diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/IdentifiedRegion.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/IdentifiedRegion.java new file mode 100644 index 000000000..6a5f51642 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/IdentifiedRegion.java @@ -0,0 +1,29 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; + +public class IdentifiedRegion extends Record { + + /** + * Constructor + * @param mainCodec MainCodec reference + */ + public IdentifiedRegion(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + /** + * @desc Predefined field lengths + */ + private void setLengths() { + mainCodec.setHint("RegionDictionaryLen", "8"); + } + +} // End of class IdentifiedRegion \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/IntX.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/IntX.java new file mode 100644 index 000000000..916a12ec4 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/IntX.java @@ -0,0 +1,86 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Integer; +import org.etsi.ttcn.tci.IntegerValue; +import org.etsi.ttcn.tci.Type; +import org.etsi.ttcn.tci.Value; + +/** + * @desc Codec for an integer of variable length + * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.1 IntX + */ +public class IntX extends Integer { + + /** + * Specialised constructor + * @param mainCodec The MainCodec reference + */ + public IntX(MainCodec mainCodec) { + super(mainCodec); + } + + /** + * @desc Decoder for an integer of variable length + */ + @Override + public Value decode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> IntX.decode: " + decodingHypothesis.getName()); + + // Read the first byte + byte msb = buf.getBytes(0, 1)[0]; + if ((msb & 0x80) == 0x00) { // Integer < 128 + mainCodec.setHint("IntXLen", "8"); + return super.decode(buf, decodingHypothesis); + } else { + // Decode the length. The encoding of the length shall use at most 7 bits set to 1 (see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.1 IntX) + byte bit; + byte byteLen = 1; + do { + bit = (byte) ((byte) (msb << byteLen++) & 0x80); + } while (bit != 0x00); + // Set the IntX length + mainCodec.setHint(decodingHypothesis.getName() + "Len", String.valueOf(byteLen * Byte.SIZE )); + // Remove the length from the real integer value + byte[] newBuf = buf.getBytes(); + newBuf[0] &= (byte)(Math.pow(2.0, 8 - byteLen + 1) - 1); + CodecBuffer newBuffer = new CodecBuffer(newBuf); + buf.overwriteWith(newBuffer); + // Decode it + return super.decode(buf, decodingHypothesis); + } + } + + /** + * @desc Encoder for an integer of variable length + */ + @Override + public CodecBuffer encode(Value value) { +// System.out.println(">>> IntX.encode: " + value.getType().getName()); + + if (mainCodec.getTciCDRequired().getInteger((IntegerValue)value) < 128) { + mainCodec.setHint("IntXLen", "8"); + return super.encode(value); + } else { + long iv = mainCodec.getTciCDRequired().getInteger((IntegerValue)value); + long bitLen = TlsHelper.getInstance().bitLength(iv); + long byteLen = TlsHelper.getInstance().byteLength(bitLen); + long flags = (long) ((byteLen | 1) << (byteLen * Byte.SIZE - TlsHelper.getInstance().bitLength(byteLen) - 1)); + long len = (long) (byteLen << (byteLen * Byte.SIZE - TlsHelper.getInstance().bitLength(byteLen) - 1)); + if ((flags & iv) != 0) { // We can encode the length on the MSB part + byteLen += 1; + len = (long) (byteLen << (byteLen * Byte.SIZE - TlsHelper.getInstance().bitLength(byteLen))); + } + mainCodec.setHint("integerLen", String.valueOf(byteLen * Byte.SIZE )); + IntegerValue newValue = mainCodec.getTciCDRequired().setInteger((int)(iv | len)); + return super.encode(newValue); + } + } + +} // End of class IntX diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/ItsAidSsp.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/ItsAidSsp.java new file mode 100644 index 000000000..e2b0388b0 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/ItsAidSsp.java @@ -0,0 +1,56 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class ItsAidSsp extends Record { + + public ItsAidSsp(MainCodec mainCodec) { + super(mainCodec); +// setLengths(); + } + +// private void setLengths() { +// mainCodec.setHint("Bit2Len", "2"); +// mainCodec.setHint("Bit3Len", "3"); +// } +// + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> ItsAidSsp.postEncodeField: " + fieldName); + + if (fieldName.equals("service_specific_permissions")) { + CodecBuffer bufLen = new CodecBuffer(new byte[] { (byte)buf.getNbBytes() } ); + System.out.println("ItsAidSsp.postEncodeField: bufLen = " + bufLen); + bufLen.append(buf); + buf.overwriteWith(bufLen); + } + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> ItsAidSsp.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("service_specific_permissions")) { + int len = buf.readBits(Byte.SIZE)[0]; // FIXME It depends of the len value : <= 127 or > 127 + // FIXME Check for opaque length encoding + //int len = ByteHelper.byteArrayToInt(buf.readBits(Integer.SIZE)); // field_sizeLen is 1 bytes +// System.out.println("ItsAidSsp.preDecodeField: len = " + len); + mainCodec.setHint("Oct1to31Len", Integer.toString(len)); + } + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> ItsAidSsp.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class ItsAidSsp \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/Plugin.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/Plugin.java new file mode 100644 index 000000000..bde62d813 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/Plugin.java @@ -0,0 +1,126 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecFactory; +import org.etsi.ttcn.codec.generic.Union; +import org.etsi.ttcn.tci.TciTypeClass; + +public class Plugin { + + public static void init() { + CodecFactory cf = CodecFactory.getInstance(); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "AcEnableSecurity", AcEnableSecurity.class); + // Draft ETSI TS 103 097 V1.1.14 Clause 4.2 Specification of basic format elements + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "PublicKey", PublicKey.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "EccPoint", EccPoint.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "AesCcm", AesCcm.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "SignerInfo", SignerInfo.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "Signature", Signature.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "EcdsaSignature", EcdsaSignature.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "Time64WithStandardDeviation", Time64WithStandardDeviation.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "Duration", Duration.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "TwoDLocation", TwoDLocation.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "ThreeDLocation", ThreeDLocation.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "EncryptionParameters", EncryptionParameters.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "GeographicRegion", GeographicRegion.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "CircularRegion", CircularRegion.class); + + cf.setCodec(TciTypeClass.UNION, "LibItsSecurity", "SignerInfoContainer", SignerInfoContainer.class); + cf.setCodec(TciTypeClass.UNION, "LibItsSecurity", "EncryptionParametersContainer", EncryptionParametersContainer.class); + cf.setCodec(TciTypeClass.UNION, "LibItsSecurity", "GeographicRegionContainer", GeographicRegionContainer.class); + + cf.setCodec(TciTypeClass.ENUMERATED, "LibItsSecurity", "RegionDictionary", RegionDictionary.class); + + cf.setCodec(TciTypeClass.INTEGER, "LibItsSecurity", "Time32", Time32.class); + cf.setCodec(TciTypeClass.INTEGER, "LibItsSecurity", "Time64", Time64.class); + cf.setCodec(TciTypeClass.INTEGER, "LibItsSecurity", "IntX", IntX.class); + + // Draft ETSI TS 103 097 V1.1.14 Clause 5 Specification of security header + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "SecuredMessage", SecuredMessage.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "HeaderField", HeaderField.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "SecPayload", SecPayload.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "TrailerField", TrailerField.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "RecipientInfo", RecipientInfo.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "EciesEncryptedKey", EciesEncryptedKey.class); + + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "HeaderFields", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "IntXs", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "HashedId3s", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "RecipientInfos", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "TrailerFields", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "RectangularRegions", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "PolygonalRegion", RecordOf.class); + // Change record of into set of in order to use superset + // record of shall be used, refer to ETSI TS 103 097 V 1.1.6 (2014-05) + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "HeaderFields", RecordOf.class); + + cf.setCodec(TciTypeClass.UNION, "LibItsSecurity", "PublicKeyContainer", Union.class); + cf.setCodec(TciTypeClass.UNION, "LibItsSecurity", "EccPointContainer", Union.class); + cf.setCodec(TciTypeClass.UNION, "LibItsSecurity", "SignatureContainer", Union.class); + + cf.setCodec(TciTypeClass.UNION, "LibItsSecurity", "HeaderFieldContainer", HeaderFieldContainer.class); + cf.setCodec(TciTypeClass.UNION, "LibItsSecurity", "RecipientInfoContainer", RecipientInfoContainer.class); + cf.setCodec(TciTypeClass.UNION, "LibItsSecurity", "TrailerFieldContainer", TrailerFieldContainer.class); + + // Draft ETSI TS 103 097 V1.1.14 Clause 6 Specification of certificate format + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "ToBeSignedCertificate", ToBeSignedCertificate.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "Certificate", Certificate.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "SubjectInfo", SubjectInfo.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "SubjectAssurance", SubjectAssurance.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "SubjectAttribute", SubjectAttribute.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "ValidityRestriction", ValidityRestriction.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "ItsAidSsp", ItsAidSsp.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "ServiceSpecificPermissions", ServiceSpecificPermissions.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "SspDENM", SspDENM.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "CertificateWithAlgo", CertificateWithAlgo.class); + + cf.setCodec(TciTypeClass.UNION, "LibItsSecurity", "SubjectAttributeContainer", SubjectAttributeContainer.class); + cf.setCodec(TciTypeClass.UNION, "LibItsSecurity", "ValidityRestrictionContainer", ValidityRestrictionContainer.class); + + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "CertificateChain", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "ValidityRestrictions", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "SubjectAttributes", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "ItsAidSsps", RecordOf.class); + // Change record of into set of in order to use superset + // record of shall be used, refer to ETSI TS 103 097 V 1.1.6 (2014-05) + + // TCT3 specific + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "PublicKeyContainer.eccPoint", EccPoint.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "SignatureContainer.ecdsa_signature", EcdsaSignature.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "PublicKeyContainer.aesCcm", Signature.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "HeaderFieldContainer.signer", SignerInfo.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "EncryptionParametersContainer.public_key", EncryptionParameters.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "GeographicRegionContainer.circular_region", CircularRegion.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "GeographicRegionContainer.id_region", IdentifiedRegion.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "HeaderFieldContainer.generation_time_with_standard_deviation", HeaderField.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "HeaderFieldContainer.generation_location", HeaderField.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "HeaderFieldContainer.enc_params", EncryptionParameters.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "RecipientInfoContainer.enc_key", EciesEncryptedKey.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "RecipientInfoContainer.enc_key_other", RecipientInfoContainer.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "TrailerFieldContainer.signature_", Signature.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "TrailerFieldContainer.security_field", TrailerFieldContainer.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "SubjectAttributeContainer.key", PublicKey.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "SubjectAttributeContainer.rv", EccPoint.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "SubjectAttributeContainer.assurance_level", SubjectAssurance.class); + cf.setCodec(TciTypeClass.RECORD, "LibItsSecurity", "ValidityRestrictionContainer.region", GeographicRegion.class); + + cf.setCodec(TciTypeClass.INTEGER, "LibItsSecurity", "HeaderFieldContainer.generation_time", Time64.class); + cf.setCodec(TciTypeClass.INTEGER, "LibItsSecurity", "HeaderFieldContainer.expiry_time", Time32.class); + cf.setCodec(TciTypeClass.INTEGER, "LibItsSecurity", "HeaderFieldContainer.its_aid", IntX.class); + cf.setCodec(TciTypeClass.INTEGER, "LibItsSecurity", "ValidityRestrictionContainer.end_validity", Time32.class); + + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "GeographicRegionContainer.rectangular_region", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "GeographicRegionContainer.polygonal_region", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "HeaderFieldContainer.digests", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "HeaderFieldContainer.recipients", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "SubjectAttributeContainer.its_aid_list", RecordOf.class); + cf.setCodec(TciTypeClass.SET_OF, "LibItsSecurity", "SubjectAttributeContainer.its_aid_ssp_list", RecordOf.class); + // Change record of into set of in order to use superset + // record of shall be used, refer to ETSI TS 103 097 V 1.1.6 (2014-05) + + } +} // End of class Plugin \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/PublicKey.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/PublicKey.java new file mode 100644 index 000000000..f3179567d --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/PublicKey.java @@ -0,0 +1,49 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class PublicKey extends Record { + + /** + * List of supported algorithms based on public key cryptography + */ + final byte c_ecdsa_nistp256_with_sha256 = 0x00; + /** + * List of supported algorithms based on public key cryptography + */ + final byte c_ecies_nistp2561 = 0x01; + + public PublicKey(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("PublicKeyAlgorithmLen", "8"); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> PublicKey.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("algorithm")) { + if (buf.getBytes(0, 1)[0] == c_ecdsa_nistp256_with_sha256) { + mainCodec.setHint("PublicKeyContainer", "eccPoint"); // Set variant + } else if (buf.getBytes(0, 1)[0] == c_ecies_nistp2561) { + mainCodec.setHint("PublicKeyContainer", "aesCcm"); // Set variant + } else { + mainCodec.setHint("PublicKeyContainer", "other_key"); // Set variant + } + } + } + +} // End of class PublicKey diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/RecipientInfo.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/RecipientInfo.java new file mode 100644 index 000000000..dfd1be930 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/RecipientInfo.java @@ -0,0 +1,48 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class RecipientInfo extends Record { + + final byte c_ecies_nistp2561 = 0x01; /** List of supported algorithms based on public key cryptography */ + + public RecipientInfo(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("HashedId8Len", "8"); + mainCodec.setHint("PublicKeyAlgorithmLen", "8"); + mainCodec.setHint("Oct20Len", "20"); + } + + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> RecipientInfo.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("pk_encryption")) { + if (buf.getBytes(0, 1)[0] == c_ecies_nistp2561) { + mainCodec.setHint("RecipientInfoContainer", "enc_key"); // Set variant + } else { + mainCodec.setHint("RecipientInfoContainer", "enc_key_other"); // Set variant + } + } + } + + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> RecipientInfo.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> RecipientInfo.postEncodeField: " + fieldName); + } +} // End of class RecipientInfo \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/RecipientInfoContainer.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/RecipientInfoContainer.java new file mode 100644 index 000000000..91eb620e8 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/RecipientInfoContainer.java @@ -0,0 +1,30 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Union; +import org.etsi.ttcn.tci.OctetstringValue; +import org.etsi.ttcn.tci.UnionValue; + +public class RecipientInfoContainer extends Union { + + public RecipientInfoContainer(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void preEncode(CodecBuffer buf, UnionValue uv) { +// System.out.println(">>> RecipientInfoContainer.preEncode: " + uv.getType().getName() + ", " + uv.getPresentVariantName()); + + if (uv.getPresentVariantName().equals("enc_key_other")) { + // FIXME Check for opaque length encoding depending of the length value : <= 127 or > 127 + buf.appendBytes(new byte[] { (byte)((OctetstringValue)(uv.getVariant(uv.getPresentVariantName()))).getLength() } ); + } + } + +} // End of class RecipientInfoContainer diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/RecordOf.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/RecordOf.java new file mode 100644 index 000000000..5d1c2d27d --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/RecordOf.java @@ -0,0 +1,60 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import java.util.ArrayList; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.tci.RecordOfValue; +import org.etsi.ttcn.tci.Type; +import org.etsi.ttcn.tci.Value; + +public class RecordOf extends org.etsi.ttcn.codec.generic.RecordOf { + + public RecordOf(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + public Value decode(CodecBuffer buf, Type decodingHypothesis) { +// System.out.println(">>> security.RecordOf.decode: " + decodingHypothesis.getName()); + + int len = (int) TlsHelper.getInstance().tls2size(buf);// buf.readBytes(1)[0]; // Get number of items into the RecordOf + if (len == 0) { + RecordOfValue rov = (RecordOfValue)decodingHypothesis.newInstance(); + rov.setLength(0); + return rov; + } + CodecBuffer newBuf = new CodecBuffer(buf.readBits(len * Byte.SIZE)); + + ArrayList recordOf = new ArrayList(); + RecordOfValue rov = (RecordOfValue)decodingHypothesis.newInstance(); + while (newBuf.getNbBits() != 0) { + recordOf.add(mainCodec.decode(newBuf, rov.getElementType())); + } + + // Fill it + rov.setLength(recordOf.size()); + for (int position = 0; position < recordOf.size(); position++) { + rov.setField(position, recordOf.get(position)); + } // End of 'for' statement + + return rov; + } + + + @Override + public CodecBuffer encode(Value value) { +// System.out.println(">>> security.RecordOf.encode: " + value.getType().getName()); + + CodecBuffer buf = super.encode(value); + CodecBuffer bufLen = new CodecBuffer(TlsHelper.getInstance().size2tls(buf.getNbBytes())); + bufLen.append(buf); + return bufLen; + } + +} // End of class RecordOf diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/RegionDictionary.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/RegionDictionary.java new file mode 100644 index 000000000..d2a407297 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/RegionDictionary.java @@ -0,0 +1,22 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Enumerated; + +public class RegionDictionary extends Enumerated { + + public RegionDictionary(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("RegionDictionaryLen", "8"); + } + +} // End of class RegionDictionary \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/SecPayload.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/SecPayload.java new file mode 100644 index 000000000..723d9805c --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/SecPayload.java @@ -0,0 +1,56 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class SecPayload extends Record { + + final byte c_signed_external = 0x03; + + public SecPayload(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("SecPayloadTypeLen", "8"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> SecPayload.postEncodeField: " + fieldName); + + if (fieldName.equals("data")) { + // Store first the octetstring length as specified in Draft ETSI TS 103 097 V1.1.14 Clause 4.2 + CodecBuffer bufLen = new CodecBuffer(new byte[] { (byte)buf.getNbBytes() } ); + bufLen.append(buf); + buf.overwriteWith(bufLen); + } + } + + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> SecPayload.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("type_")) { + mainCodec.setPresenceHint("data", buf.getBytes(0, 1)[0] != c_signed_external); + } else if (fieldName.equals("data") && (mainCodec.getPresenceHint("data") == true)) { + int len = buf.readBits(Byte.SIZE)[0]; // field_sizeLen is 1 bytes + System.out.println("SecPayload.preDecodeField: len = " + len); + mainCodec.setHint("octetstringLen", Integer.toString(len)); + } + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> SecPayload.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class SecPayload \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/SecuredMessage.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/SecuredMessage.java new file mode 100644 index 000000000..06a9a9290 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/SecuredMessage.java @@ -0,0 +1,24 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; + +public class SecuredMessage extends Record { + + public SecuredMessage(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> SecuredMessage.postEncodeField: " + fieldName); + + } + +} // End of class SecuredMessage \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/ServiceSpecificPermissions.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/ServiceSpecificPermissions.java new file mode 100644 index 000000000..20ac94cd8 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/ServiceSpecificPermissions.java @@ -0,0 +1,59 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.common.ByteHelper; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class ServiceSpecificPermissions extends Record { + + public ServiceSpecificPermissions(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("Oct1Len", "1"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> ServiceSpecificPermissions.postEncodeField: " + fieldName); + + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> ServiceSpecificPermissions.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("version")) { + byte version = buf.getBytes(0, 1)[0]; + switch (version) { + case (byte)0x01: + mainCodec.setHint("version", String.valueOf(version)); + break; + } // End of 'switch' statement + } else if (fieldName.equals("sspContainer")) { + if (mainCodec.getHint("version") != null) { + mainCodec.setPresenceHint(fieldName, true); + mainCodec.setHint("ServiceSpecificPermissionsContainer", "sspDENM"); + } else { + mainCodec.setPresenceHint(fieldName, false); + + } + } + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> ServiceSpecificPermissions.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class ServiceSpecificPermissions diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/Signature.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/Signature.java new file mode 100644 index 000000000..e996661d0 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/Signature.java @@ -0,0 +1,46 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class Signature extends Record { + + /** + * List of supported algorithms based on public key cryptography + */ + final byte e_ecdsa_nistp256_with_sha256 = 0x00; + /** + * List of supported algorithms based on public key cryptography + */ + final byte e_ecies_nistp2561 = 0x01; + + public Signature(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("PublicKeyAlgorithmLen", "8"); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> Signature.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + if (fieldName.equals("algorithm")) { + if (buf.getBytes(0, 1)[0] == e_ecdsa_nistp256_with_sha256) { + mainCodec.setHint("SignatureContainer", "ecdsa_signature"); + } else if (buf.getBytes(0, 1)[0] == e_ecies_nistp2561) { + mainCodec.setHint("SignatureContainer", "signature_"); + } + } + } + +} // End of class Signature diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/SignerInfo.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/SignerInfo.java new file mode 100644 index 000000000..c1c46a662 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/SignerInfo.java @@ -0,0 +1,77 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +/** + * @desc Information about the signer of a message + * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.10 SignerInfo + */ +public class SignerInfo extends Record { + + final byte c_self = 0x00; /** The data is self-signed */ + final byte c_certificate_digest_with_sha256 = 0x01; /** An 8 octet digest of the relevant certificate */ + final byte c_certificate = 0x02; /** The relevant certificate itself */ + final byte c_certificate_chain = 0x03; /** A complete certificate chain */ + final byte c_certificate_digest_with_other_algorithm = 0x04; /** An 8 octet digest */ + + /** + * Constructor + * @param mainCodec MainCodec reference + */ + public SignerInfo(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + /** + * @desc Predefined field lengths + */ + private void setLengths() { + mainCodec.setHint("SignerInfoTypeLen", "8"); + mainCodec.setHint("HashedId8Len", "8"); + } + + /** + * @desc Set the variant according to the SignerInfo type + * @see See Draft ETSI TS 103 097 V1.1.14 Clause 4.2.11 SignerInfoType + */ + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> SignerInfo.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("type_")) { + byte type_ = buf.getBytes(0, 1)[0]; + mainCodec.setPresenceHint("signerInfo", (boolean)(type_ != c_self)); + switch (type_) { + case (byte)c_self: + // Nothing to do + break; + case (byte)c_certificate_digest_with_sha256: + mainCodec.setHint("SignerInfoContainer", "digest"); + break; + case (byte)c_certificate: + mainCodec.setHint("SignerInfoContainer", "certificate"); + break; + case (byte)c_certificate_chain: + mainCodec.setHint("SignerInfoContainer", "certificates"); + break; + case (byte)c_certificate_digest_with_other_algorithm: + mainCodec.setHint("SignerInfoContainer", "certificateWithAlgo"); + break; + default: + mainCodec.setHint("SignerInfoContainer", "info"); + break; + } // End of 'switch' statement + } + } + +} // End of class SignerInfo \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/SignerInfoContainer.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/SignerInfoContainer.java new file mode 100644 index 000000000..81734622e --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/SignerInfoContainer.java @@ -0,0 +1,31 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Union; +import org.etsi.ttcn.tci.OctetstringValue; +import org.etsi.ttcn.tci.UnionValue; + +public class SignerInfoContainer extends Union { + + public SignerInfoContainer(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void preEncode(CodecBuffer buf, UnionValue uv) { +// System.out.println(">>> SignerInfoContainer.preEncode: " + uv.getType().getName() + ", " + uv.getPresentVariantName()); + + if (uv.getPresentVariantName().equals("certificates")) { + // TODO To be continued + } else if (uv.getPresentVariantName().equals("info")) { + buf.appendBytes(new byte[] { (byte)((OctetstringValue)(uv.getVariant(uv.getPresentVariantName()))).getLength() } ); + } + } + +} // End of class SignerInfoContainer diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/SspDENM.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/SspDENM.java new file mode 100644 index 000000000..bbb0c6af0 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/SspDENM.java @@ -0,0 +1,39 @@ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.common.ByteHelper; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class SspDENM extends Record { + + public SspDENM(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("Bit1Len", "1"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> SspDENM.postEncodeField: " + fieldName); + + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> SspDENM.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> SspDENM.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + } + +} // End of class SspDENM diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectAssurance.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectAssurance.java new file mode 100644 index 000000000..1cd77c3d9 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectAssurance.java @@ -0,0 +1,41 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class SubjectAssurance extends Record { + + public SubjectAssurance(MainCodec mainCodec) { + super(mainCodec); +// setLengths(); +// } +// +// private void setLengths() { +// mainCodec.setHint("Bit2Len", "2"); +// mainCodec.setHint("Bit3Len", "3"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> SubjectAssurance.postEncodeField: " + fieldName); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> SubjectAssurance.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> SubjectAssurance.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class SubjectAssurance \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectAttribute.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectAttribute.java new file mode 100644 index 000000000..eddecdf27 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectAttribute.java @@ -0,0 +1,73 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class SubjectAttribute extends Record { + + final byte c_verification_key = 0x00; + final byte c_encryption_key = 0x01; + final byte c_assurance_level = 0x02; + final byte c_reconstruction_value = 0x03; + final byte c_its_aid_list = 0x20; + final byte c_its_aid_ssp_list = 0x21; + + public SubjectAttribute(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("SubjectAttributeTypeLen", "8"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> SubjectAttribute.postEncodeField: " + fieldName); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> SubjectAttribute.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("type_")) { + byte type_ = buf.getBytes(0, 1)[0]; + switch (type_) { + case (byte)c_verification_key: + // No break; + case (byte)c_encryption_key: + mainCodec.setHint("SubjectAttributeContainer", "key"); // Set variant + break; + case (byte)c_reconstruction_value: + mainCodec.setHint("SubjectAttributeContainer", "rv"); // Set variant + break; + case (byte)c_assurance_level: + mainCodec.setHint("SubjectAttributeContainer", "assurance_level"); // Set variant + break; + case (byte)c_its_aid_list: + mainCodec.setHint("SubjectAttributeContainer", "its_aid_list"); // Set variant + break; + case (byte)c_its_aid_ssp_list: + mainCodec.setHint("SubjectAttributeContainer", "its_aid_ssp_list"); // Set variant + break; + default: + mainCodec.setHint("SubjectAttributeContainer", "other_attribute"); // Set variant + break; + } // End of 'switch' statement + } + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> SubjectAttribute.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class SubjectAttribute \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectAttributeContainer.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectAttributeContainer.java new file mode 100644 index 000000000..c6e2fa3e6 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectAttributeContainer.java @@ -0,0 +1,29 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Union; +import org.etsi.ttcn.tci.OctetstringValue; +import org.etsi.ttcn.tci.UnionValue; + +public class SubjectAttributeContainer extends Union { + + public SubjectAttributeContainer(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void preEncode(CodecBuffer buf, UnionValue uv) { +// System.out.println(">>> SubjectAttributeContainer.preEncode: " + uv.getType().getName() + ", " + uv.getPresentVariantName()); + + if (uv.getPresentVariantName().equals("other_attribute")) { + buf.appendBytes(new byte[] { (byte)((OctetstringValue)(uv.getVariant(uv.getPresentVariantName()))).getLength() } ); + } + } + +} // End of class SubjectAttributeContainer diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectInfo.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectInfo.java new file mode 100644 index 000000000..30aad76a1 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/SubjectInfo.java @@ -0,0 +1,54 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class SubjectInfo extends Record { + + public SubjectInfo(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("SubjectTypeLen", "8"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> SubjectInfo.postEncodeField: " + fieldName); + + if (fieldName.equals("subject_name")) { + CodecBuffer bufLen = new CodecBuffer(new byte[] { (byte)buf.getNbBytes() } ); + bufLen.append(buf); + buf.overwriteWith(bufLen); + } + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> SubjectInfo.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("subject_name")) { + int len = buf.readBits(Byte.SIZE)[0]; // FIXME It depends of the len value : <= 127 or > 127 + // FIXME Check for opaque length encoding + //int len = ByteHelper.byteArrayToInt(buf.readBits(Integer.SIZE)); // field_sizeLen is 1 bytes +// System.out.println("SubjectInfo.preDecodeField: len = " + len); + mainCodec.setHint("Oct0to31Len", Integer.toString(len)); + } + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> SubjectInfo.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class SubjectInfo \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/ThreeDLocation.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/ThreeDLocation.java new file mode 100644 index 000000000..e77aafa3b --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/ThreeDLocation.java @@ -0,0 +1,34 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class ThreeDLocation extends Record { + + public ThreeDLocation(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("WGSLatitudeLen", "32"); + mainCodec.setHint("WGSLongitudeLen", "32"); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> ThreeDLocation.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + if (fieldName.equals("elevation")) { + mainCodec.setHint("Oct2Len", "2"); + } + } + +} // End of class ThreeDLocation \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/Time32.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/Time32.java new file mode 100644 index 000000000..e0bc5f5a9 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/Time32.java @@ -0,0 +1,24 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Integer; + +public class Time32 extends Integer { + + public Time32(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("Time32Len", "32"); + mainCodec.setHint("HeaderFieldContainer.expiry_timeLen", "32"); + mainCodec.setHint("ValidityRestrictionContainer.end_validityLen", "32"); + } + +} // End of class Time32 \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/Time64.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/Time64.java new file mode 100644 index 000000000..d04da83b5 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/Time64.java @@ -0,0 +1,23 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Integer; + +public class Time64 extends Integer { + + public Time64(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("Time64Len", "64"); + mainCodec.setHint("HeaderFieldContainer.generation_timeLen", "64"); + } + +} // End of class Time64 \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/Time64WithStandardDeviation.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/Time64WithStandardDeviation.java new file mode 100644 index 000000000..0eb276eb4 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/Time64WithStandardDeviation.java @@ -0,0 +1,25 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; + +public class Time64WithStandardDeviation extends Record { + + public Time64WithStandardDeviation(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + /** + * @desc Predefined field lengths + */ + private void setLengths() { + mainCodec.setHint("Time64Len", "64"); + } + +} // End of Time64WithStandardDeviation diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/TlsHelper.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/TlsHelper.java new file mode 100644 index 000000000..d3f4a36e3 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/TlsHelper.java @@ -0,0 +1,74 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.common.ByteHelper; + +public class TlsHelper { + + private static TlsHelper Instance = new TlsHelper(); + + public static TlsHelper getInstance() { return Instance; } + + private TlsHelper() { + } + + public byte[] size2tls(final int length) { + byte[] result = null; + if (length < 128) { // One byte length + result = new byte[] { (byte)length }; + } else { + long lv = length; + long bitLen = bitLength(lv); + long byteLen = byteLength(bitLen); + long flags = (long) ((byteLen | 1) << (byteLen * Byte.SIZE - bitLength(byteLen) - 1)); + long len = (long) (byteLen << (byteLen * Byte.SIZE - bitLength(byteLen) - 1)); + if ((flags & lv) != 0) { // We can encode the length on the MSB part + byteLen += 1; + len = (long) (byteLen << (byteLen * Byte.SIZE - bitLength(byteLen)) - 1); + } + result = ByteHelper.longToByteArray((long)(lv | len), (int) byteLen); + } + + return result; + } + + public long tls2size(CodecBuffer buf) { + // Sanity check + if (buf.getNbBytes() == 0) { + return 0; + } + + // Read the first byte + byte msb = buf.readBits(Byte.SIZE)[0]; + if ((msb & 0x80) == 0x00) { // Integer < 128 + return msb; + } else { + // Decode the length. The encoding of the length shall use at most 7 bits set to 1 (see Draft ETSI TS 103 097 V1.1.14 Clause 4.1 Presentation Language Table 1/8) + byte bit; + byte byteLen = 1; + do { + bit = (byte) ((byte) (msb << byteLen++) & 0x80); + } while (bit != 0x00); + // Set the IntX length + byte[] length = ByteHelper.concat(new byte[] { msb }, buf.readBytes(byteLen - 1)); + length[0] &= (byte)(Math.pow(2.0, 8 - byteLen + 1) - 1); + long lv = ByteHelper.byteArrayToLong(length); + return lv; + } + } + + public long bitLength(final long value) { + return (long) Math.ceil(Math.log(value) / Math.log(2)); + } + + public long byteLength(final long value) { + double d = value; // Convert int to double + return (long) Math.ceil(d / Byte.SIZE); + } + +} // End of class TlsHelper diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/ToBeSignedCertificate.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/ToBeSignedCertificate.java new file mode 100644 index 000000000..4a2f3eb2e --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/ToBeSignedCertificate.java @@ -0,0 +1,44 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class ToBeSignedCertificate extends Record { + + /** + * List of supported algorithms based on public key cryptography + */ + final byte e_ecdsa_nistp256_with_sha256 = 0x00; + /** + * List of supported algorithms based on public key cryptography + */ + final byte e_ecies_nistp2561 = 0x01; + + public ToBeSignedCertificate(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> ToBeSignedCertificate.postEncodeField: " + fieldName); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> ToBeSignedCertificate.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> ToBeSignedCertificate.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class ToBeSignedCertificate diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/TrailerField.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/TrailerField.java new file mode 100644 index 000000000..33227d326 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/TrailerField.java @@ -0,0 +1,59 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +/** + * @desc Information used by the security layer after processing the payload + * @see Draft ETSI TS 103 097 V1.1.14 Clause 5.6 TrailerField + */ +public class TrailerField extends Record { + + final byte c_signature = 0x01; + + /** + * Constructor + * @param mainCodec MainCodec reference + */ + public TrailerField(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + /** + * @desc Predefined field lengths + */ + private void setLengths() { + mainCodec.setHint("TrailerFieldTypeLen", "8"); + } + + /** + * @desc Set the variant according to the TrailerField type + * @see See Draft ETSI TS 103 097 V1.1.14 Clause 5.7 TrailerFieldType + */ + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> TrailerField.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("type_")) { + byte type_ = buf.getBytes(0, 1)[0]; + switch (type_) { + case (byte)c_signature: + mainCodec.setHint("TrailerFieldContainer", "signature_"); + break; + default: + mainCodec.setHint("TrailerFieldContainer", "security_field"); + break; + } // End of 'switch' statement + } + } + +} // End of class TrailerField \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/TrailerFieldContainer.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/TrailerFieldContainer.java new file mode 100644 index 000000000..e783c8066 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/TrailerFieldContainer.java @@ -0,0 +1,30 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Union; +import org.etsi.ttcn.tci.OctetstringValue; +import org.etsi.ttcn.tci.UnionValue; + +public class TrailerFieldContainer extends Union { + + public TrailerFieldContainer(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void preEncode(CodecBuffer buf, UnionValue uv) { +// System.out.println(">>> TrailerFieldContainer.preEncode: " + uv.getType().getName() + ", " + uv.getPresentVariantName()); + + if (uv.getPresentVariantName().equals("security_field")) { + // FIXME Check for opaque length encoding depending of the length value : <= 127 or > 127 + buf.appendBytes(new byte[] { (byte)((OctetstringValue)(uv.getVariant(uv.getPresentVariantName()))).getLength() } ); + } + } + +} // End of class TrailerFieldContainer diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/TwoDLocation.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/TwoDLocation.java new file mode 100644 index 000000000..0daacbb39 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/TwoDLocation.java @@ -0,0 +1,23 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; + +public class TwoDLocation extends Record { + + public TwoDLocation(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("WGSLatitudeLen", "32"); + mainCodec.setHint("WGSLongitudeLen", "32"); + } + +} // End of class TwoDLocation \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/ValidityRestriction.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/ValidityRestriction.java new file mode 100644 index 000000000..56ce8161a --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/ValidityRestriction.java @@ -0,0 +1,66 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Record; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.Type; + +public class ValidityRestriction extends Record { + + final byte c_time_end = 0x00; + final byte c_time_start_and_end = 0x01; + final byte c_time_start_and_duration = 0x02; + final byte c_region = 0x03; + + public ValidityRestriction(MainCodec mainCodec) { + super(mainCodec); + setLengths(); + } + + private void setLengths() { + mainCodec.setHint("ValidityRestrictionTypeLen", "8"); + } + + @Override + protected void postEncodeField(String fieldName, CodecBuffer buf) { +// System.out.println(">>> ValidityRestriction.postEncodeField: " + fieldName); + } + + @Override + protected void preDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> ValidityRestriction.preDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + + if (fieldName.equals("type_")) { + byte type_ = buf.getBytes(0, 1)[0]; + switch (type_) { + case (byte)c_time_end: + mainCodec.setHint("ValidityRestrictionContainer", "end_validity"); // Set variant + break; + case (byte)c_time_start_and_end: + mainCodec.setHint("ValidityRestrictionContainer", "time_start_and_end"); // Set variant + break; + case (byte)c_time_start_and_duration: + mainCodec.setHint("ValidityRestrictionContainer", "time_start_and_duration"); // Set variant + break; + case (byte)c_region: + mainCodec.setHint("ValidityRestrictionContainer", "region"); // Set variant + break; + default: + mainCodec.setHint("SubjectAttributeContainer", "data"); // Set variant + break; + } // End of 'switch' statement + } + } + + @Override + protected void postDecodeField(String fieldName, CodecBuffer buf, Type decodingHypothesis, RecordValue rv) { +// System.out.println(">>> ValidityRestriction.postDecodeField: " + fieldName + ", " + decodingHypothesis.getName() + ", " + rv.getType().getName()); + } + +} // End of class ValidityRestriction \ No newline at end of file diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/security/ValidityRestrictionContainer.java b/javasrc/codec/org/etsi/ttcn/codec/its/security/ValidityRestrictionContainer.java new file mode 100644 index 000000000..c256de4f2 --- /dev/null +++ b/javasrc/codec/org/etsi/ttcn/codec/its/security/ValidityRestrictionContainer.java @@ -0,0 +1,29 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.ttcn.codec.its.security; + +import org.etsi.ttcn.codec.CodecBuffer; +import org.etsi.ttcn.codec.MainCodec; +import org.etsi.ttcn.codec.generic.Union; +import org.etsi.ttcn.tci.OctetstringValue; +import org.etsi.ttcn.tci.UnionValue; + +public class ValidityRestrictionContainer extends Union { + + public ValidityRestrictionContainer(MainCodec mainCodec) { + super(mainCodec); + } + + @Override + protected void preEncode(CodecBuffer buf, UnionValue uv) { +// System.out.println(">>> ValidityRestrictionContainer.preEncode: " + uv.getType().getName() + ", " + uv.getPresentVariantName()); + + if (uv.getPresentVariantName().equals("data")) { + buf.appendBytes(new byte[] { (byte)((OctetstringValue)(uv.getVariant(uv.getPresentVariantName()))).getLength() } ); + } + } + +} // End of class ValidityRestrictionContainer diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/uppertester/UtDenmTermination.java b/javasrc/codec/org/etsi/ttcn/codec/its/uppertester/UtDenmTermination.java index 6255e9087..45ed820af 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/uppertester/UtDenmTermination.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/uppertester/UtDenmTermination.java @@ -5,32 +5,18 @@ */ package org.etsi.ttcn.codec.its.uppertester; -import org.etsi.ttcn.codec.CodecBuffer; import org.etsi.ttcn.codec.MainCodec; -import org.etsi.ttcn.tci.Type; -import org.etsi.ttcn.tci.Value; public class UtDenmTermination extends UtRecord { public UtDenmTermination(MainCodec mainCodec) { super(mainCodec); - } - - @Override - public Value decode(CodecBuffer buf, Type decodingHypothesis) { setLengths(); - return super.decode(buf, decodingHypothesis); } - - @Override - public CodecBuffer preEncode(Value value) { - setLengths(); - return super.preEncode(value); - } private void setLengths() { mainCodec.setHint("StationIDLen", "32"); mainCodec.setHint("SequenceNumberLen", "16"); } - + } diff --git a/javasrc/codec/org/etsi/ttcn/codec/its/uppertester/UtPduId.java b/javasrc/codec/org/etsi/ttcn/codec/its/uppertester/UtPduId.java index cb7f82933..cbbec82d0 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/its/uppertester/UtPduId.java +++ b/javasrc/codec/org/etsi/ttcn/codec/its/uppertester/UtPduId.java @@ -76,6 +76,13 @@ public enum UtPduId { UtGn6GetInterfaceInfo(0x84), UtGn6GetInterfaceInfoResult(0x85), + /* */ + //reserved(0x90), + UtSecResult(0x91), + //reserved(0x92), + UtSec_setCertificate(0x93), + UtSec_setPrivateKey(0x94), + UtSec_setTrustPoint(0x95), /* Reserved */ reserved(0xFF); diff --git a/javasrc/codec/org/etsi/ttcn/codec/lowpan/IphcHeader.java b/javasrc/codec/org/etsi/ttcn/codec/lowpan/IphcHeader.java index e46718ac9..ca7e6d452 100644 --- a/javasrc/codec/org/etsi/ttcn/codec/lowpan/IphcHeader.java +++ b/javasrc/codec/org/etsi/ttcn/codec/lowpan/IphcHeader.java @@ -126,7 +126,8 @@ public class IphcHeader extends Record { } else if(fieldName.equals("inlineNextHeader")) { - int nh = ((IntegerValue)(rv.getField(fieldName))).getInt(); +// int nh = ((IntegerValue)(rv.getField(fieldName))).getInteger(); TTWB iterface is getInt, TCI shall be getInteger + int nh = mainCodec.getTciCDRequired().getInteger((IntegerValue)(rv.getField(fieldName))); mainCodec.setHint("Ipv6NextHeader", Integer.toString(nh)); if(nh == 0 || nh == 60 || nh == 43 || nh == 44) { mainCodec.setHint("ExtensionHeaderListMore", "true"); diff --git a/javasrc/codec/org/etsi/ttcn/common/ByteHelper.java b/javasrc/codec/org/etsi/ttcn/common/ByteHelper.java index 46e6ce58d..0541d6d0d 100644 --- a/javasrc/codec/org/etsi/ttcn/common/ByteHelper.java +++ b/javasrc/codec/org/etsi/ttcn/common/ByteHelper.java @@ -5,10 +5,12 @@ */ package org.etsi.ttcn.common; +import java.nio.ByteBuffer; + /* FIXME: to be merged with org.etsi.common.ByteHelper */ public class ByteHelper { - public static byte[] intToByteArray(int value, int length) { + public static byte[] intToByteArray(final int value, final int length) { byte[] b = new byte[length]; for (int i = length - 1; i >= 0; i--) { int offset = (b.length - 1 - i) * 8; @@ -17,7 +19,7 @@ public class ByteHelper { return b; } - public static byte[] longToByteArray(long value, int length) { + public static byte[] longToByteArray(final long value, final int length) { byte[] b = new byte[length]; for (int i = length - 1; i >= 0; i--) { int offset = (b.length - 1 - i) * 8; @@ -26,12 +28,16 @@ public class ByteHelper { return b; } + public static byte[] floatToByteArray(final float value) { + return ByteBuffer.allocate(Float.SIZE / Byte.SIZE).putFloat(value).array(); + } + /** Convert a byte array into an integer assuming that the first byte is the most significant * * @param b The byte array to convert * @return The integer value */ - public static Integer byteArrayToInt(byte[] b) { + public static Integer byteArrayToInt(final byte[] b) { // Sanity check if ((b == null) || ((b.length * Byte.SIZE) > Integer.SIZE)) { return Integer.MAX_VALUE; @@ -51,7 +57,7 @@ public class ByteHelper { * @param significantBits number of significant bits in the array * @return The integer value */ - public static int byteArrayToSignedInt(byte[] b, int significantBits) { + public static int byteArrayToSignedInt(final byte[] b, final int significantBits) { int value = 0; for (int i = 0; i < b.length; i++) { @@ -74,7 +80,7 @@ public class ByteHelper { * @param b The byte array to convert * @return The Long value */ - public static Long byteArrayToLong(byte[] b) { + public static Long byteArrayToLong(final byte[] b) { // Sanity check if ((b == null) || ((b.length * Byte.SIZE) > Long.SIZE)) { return Long.MAX_VALUE; @@ -88,7 +94,11 @@ public class ByteHelper { return new Long(value); } // End of method byteArrayToLong - public static byte[] hexStringToByteArray(String s) { + public static Float byteArrayToFloat(final byte[] b) { + return ByteBuffer.wrap(b).getFloat(); + } + + public static byte[] hexStringToByteArray(final String s) { String str = ""; for(String ss : s.split("[^0-9A-Fa-f]")) { str = str + ss; diff --git a/javasrc/common/org/etsi/common/ByteHelper.java b/javasrc/common/org/etsi/common/ByteHelper.java index 371260c1e..07cfb0d4b 100644 --- a/javasrc/common/org/etsi/common/ByteHelper.java +++ b/javasrc/common/org/etsi/common/ByteHelper.java @@ -1,5 +1,11 @@ +/** + * @author ETSI / STF462 + * @version $URL$ + * $Id$ + */ package org.etsi.common; +import java.nio.ByteBuffer; import java.nio.ByteOrder; public class ByteHelper { @@ -19,14 +25,18 @@ public class ByteHelper { return intToByteArray(value, length); } - public static byte[] intToByteArray(int value, int length) { + public static byte[] intToByteArray(int value, int length) { byte[] b = new byte[length]; for (int i = length - 1; i >= 0; i--) { int offset = (b.length - 1 - i) * 8; b[i] = (byte) ((value >>> offset) & 0xFF); } return b; - } + } + + public static byte[] floatToByteArray(final float value) { + return ByteBuffer.allocate(Float.SIZE / Byte.SIZE).putFloat(value).array(); + } public static byte[] longToByteArray(long value, int length, ByteOrder byteOrder) { if(byteOrder == ByteOrder.LITTLE_ENDIAN) { @@ -35,197 +45,201 @@ public class ByteHelper { return longToByteArray(value, length); } - public static byte[] longToByteArray(long value, int length) { + public static byte[] longToByteArray(long value, int length) { byte[] b = new byte[length]; for (int i = length - 1; i >= 0; i--) { int offset = (b.length - 1 - i) * 8; b[i] = (byte) ((value >>> offset) & 0xFF); } return b; - } - - /** Convert a byte array into a boolean - * - * @param b The byte array to convert - * @return The boolean value on success, false otherwise - */ - public static Boolean byteArrayToBoolean(byte[] b) { - // Sanity check - if ((b == null) || (b.length != 1)) { - return null; - } + } + + /** Convert a byte array into a boolean + * + * @param b The byte array to convert + * @return The boolean value on success, false otherwise + */ + public static Boolean byteArrayToBoolean(byte[] b) { + // Sanity check + if ((b == null) || (b.length != 1)) { + return null; + } - return new Boolean(b[0] == 0x01); - } // End of method byteArrayToBoolean - + return new Boolean(b[0] == 0x01); + } // End of method byteArrayToBoolean + public static Short byteArrayToShort(final byte[] b, ByteOrder byteOrder) { if(byteOrder == ByteOrder.LITTLE_ENDIAN) { return byteArrayToShort(changeEndianness(b)); } return byteArrayToShort(b); } - - /** Convert a byte array into a short value assuming that the first byte is the most significant - * - * @param b The byte array to convert - * @return The short value on success, 'Integer.MAX_VALUE' otherwise - */ - public static Short byteArrayToShort(final byte[] b) { - // Sanity check - if ((b == null) || ((b.length * Byte.SIZE) > Short.SIZE)) { - return Short.MAX_VALUE; - } + + /** Convert a byte array into a short value assuming that the first byte is the most significant + * + * @param b The byte array to convert + * @return The short value on success, 'Integer.MAX_VALUE' otherwise + */ + public static Short byteArrayToShort(final byte[] b) { + // Sanity check + if ((b == null) || ((b.length * Byte.SIZE) > Short.SIZE)) { + return Short.MAX_VALUE; + } - short value = 0; - for (Short i = 0; i < b.length; i++) { - value = (short)((value << 8) + (b[i] & 0xff)); - } + short value = 0; + for (Short i = 0; i < b.length; i++) { + value = (short)((value << 8) + (b[i] & 0xff)); + } - return new Short(value); - } // End of method byteArrayToInt - + return new Short(value); + } // End of method byteArrayToInt + public static Integer byteArrayToInt(final byte[] b, ByteOrder byteOrder) { if(byteOrder == ByteOrder.LITTLE_ENDIAN) { return byteArrayToInt(changeEndianness(b)); } return byteArrayToInt(b); } - - /** Convert a byte array into an integer assuming that the first byte is the most significant - * - * @param b The byte array to convert - * @return The integer value on success, 'Integer.MAX_VALUE' otherwise - */ - public static Integer byteArrayToInt(final byte[] b) { - // Sanity check - if ((b == null) || ((b.length * Byte.SIZE) > Integer.SIZE)) { - return Integer.MAX_VALUE; - } + + /** Convert a byte array into an integer assuming that the first byte is the most significant + * + * @param b The byte array to convert + * @return The integer value on success, 'Integer.MAX_VALUE' otherwise + */ + public static Integer byteArrayToInt(final byte[] b) { + // Sanity check + if ((b == null) || ((b.length * Byte.SIZE) > Integer.SIZE)) { + return Integer.MAX_VALUE; + } - int value = 0; - for (int i = 0; i < b.length; i++) { - value = (value << 8) + (b[i] & 0xff); - } + int value = 0; + for (int i = 0; i < b.length; i++) { + value = (value << 8) + (b[i] & 0xff); + } - return new Integer(value); - } // End of method byteArrayToInt - + return new Integer(value); + } // End of method byteArrayToInt + public static Long byteArrayToLong(final byte[] b, ByteOrder byteOrder) { if(byteOrder == ByteOrder.LITTLE_ENDIAN) { return byteArrayToLong(changeEndianness(b)); } return byteArrayToLong(b); } - - /** Convert a byte array into a Long assuming that the first byte is the most significant - * - * @param b The byte array to convert - * @return The Long value on success, 'Long.MAX_VALUE' otherwise - */ - public static Long byteArrayToLong(final byte[] b) { - // Sanity check - if ((b == null) || ((b.length * Byte.SIZE) > Long.SIZE)) { - return Long.MAX_VALUE; - } + + /** Convert a byte array into a Long assuming that the first byte is the most significant + * + * @param b The byte array to convert + * @return The Long value on success, 'Long.MAX_VALUE' otherwise + */ + public static Long byteArrayToLong(final byte[] b) { + // Sanity check + if ((b == null) || ((b.length * Byte.SIZE) > Long.SIZE)) { + return Long.MAX_VALUE; + } - long value = 0; - for (int i = 0; i < b.length; i++) { - value = (value << 8) + (b[i] & 0xff); - } + long value = 0; + for (int i = 0; i < b.length; i++) { + value = (value << 8) + (b[i] & 0xff); + } - return new Long(value); - } // End of method byteArrayToLong + return new Long(value); + } // End of method byteArrayToLong - public static byte[] hexStringToByteArray(final String s) { - String str = ""; - for(String ss : s.split("[^0-9A-Fa-f]")) { - str = str + ss; - } - int len = str.length(); - byte[] data = new byte[len / 2]; - for (int i = 0; i < len; i += 2) { - data[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4) - + Character.digit(str.charAt(i+1), 16)); - } - return data; - } - - public static byte[] concat(byte[]... arrays) { - int length = 0; - for (byte[] array : arrays) { - if(array != null) { - length += array.length; - } - } - byte[] result = new byte[length]; - int position = 0; - for (byte[] array : arrays) { - if(array != null) { - System.arraycopy(array, 0, result, position, array.length); - position += array.length; - } - } - return result; - } - - - /** Extract a sub part of a byte array - * @param array The original array - * @param offset The offset to start the extract operation - * @param length The number of bytes to extract - * @return The sub part of a provided byte array - */ - public static byte[] extract(final byte[] array, final int offset, final int length) { - // Sanity check - if ((array == null) || (array.length == 0) || (offset > array.length)) { - return null; - } + public static Float byteArrayToFloat(final byte[] b) { + return ByteBuffer.wrap(b).getFloat(); + } + + public static byte[] hexStringToByteArray(final String s) { + String str = ""; + for(String ss : s.split("[^0-9A-Fa-f]")) { + str = str + ss; + } + int len = str.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4) + + Character.digit(str.charAt(i+1), 16)); + } + return data; + } + + public static byte[] concat(byte[]... arrays) { + int length = 0; + for (byte[] array : arrays) { + if(array != null) { + length += array.length; + } + } + byte[] result = new byte[length]; + int position = 0; + for (byte[] array : arrays) { + if(array != null) { + System.arraycopy(array, 0, result, position, array.length); + position += array.length; + } + } + return result; + } + + + /** Extract a sub part of a byte array + * @param array The original array + * @param offset The offset to start the extract operation + * @param length The number of bytes to extract + * @return The sub part of a provided byte array + */ + public static byte[] extract(final byte[] array, final int offset, final int length) { + // Sanity check + if ((array == null) || (array.length == 0) || (offset > array.length)) { + return null; + } - byte[] result = new byte[length]; - System.arraycopy(array, offset, result, 0, length); - return result; - } + byte[] result = new byte[length]; + System.arraycopy(array, offset, result, 0, length); + return result; + } - /** - * This method convert a byte array containing the couple (length + string) into a string - * @param b The byte array to convert - * @return A string value - */ - public static String byteArrayWithLengthToString(final byte[] b) { - // Sanity check - if (b == null) { - return null; - } else if (b.length == 0) { - return ""; - } + /** + * This method convert a byte array containing the couple (length + string) into a string + * @param b The byte array to convert + * @return A string value + */ + public static String byteArrayWithLengthToString(final byte[] b) { + // Sanity check + if (b == null) { + return null; + } else if (b.length == 0) { + return ""; + } - // Extract the length of the string - int length = byteArrayToInt(extract(b, 0, 4)); - // Extract the the string - String result = ""; - for (int i = 0; i < length; i++) { - result += (char)(b[4 + i]); - } // End of 'for' statement + // Extract the length of the string + int length = byteArrayToInt(extract(b, 0, 4)); + // Extract the the string + String result = ""; + for (int i = 0; i < length; i++) { + result += (char)(b[4 + i]); + } // End of 'for' statement - return result; - } + return result; + } - public static String byteArrayToString(final byte[] buffer) { - - String result = ""; - if (buffer != null) { - for(int i=0; i < buffer.length; ++i) { - result += String.format("%02X", (byte)buffer[i]); - } - } + public static String byteArrayToString(final byte[] buffer) { + + String result = ""; + if (buffer != null) { + for(int i=0; i < buffer.length; ++i) { + result += String.format("%02X", (byte)buffer[i]); + } + } return result; - } - - /** - * Dump a byte array in hex/ascii mode. - * @param label The dump label - * @param buffer The byte array to dump - */ + } + + /** + * Dump a byte array in hex/ascii mode. + * @param label The dump label + * @param buffer The byte array to dump + */ public synchronized static void dump(final String label, final byte[] buffer) { if ((buffer != null) && (buffer.length != 0)) diff --git a/javasrc/common/org/etsi/common/KPM.java b/javasrc/common/org/etsi/common/KPM.java new file mode 100644 index 000000000..abf88b67a --- /dev/null +++ b/javasrc/common/org/etsi/common/KPM.java @@ -0,0 +1,61 @@ +/** + * Knuth-Morris-Pratt Algorithm implementation + * @author ETSI / STF481 + * @version $URL$ + * $Id$ + * Credit http://www.fmi.uni-sofia.bg/ + */ +package org.etsi.common; + +public class KPM { + + /** + * Search the data byte array for the first occurrence of the byte array pattern within given boundaries. + * @param data + * @param start First index in data + * @param stop Last index in data so that stop-start = length + * @param pattern What is being searched. '*' can be used as wildcard for "ANY character" + * @return + */ + public static int indexOf( byte[] data, int start, int stop, byte[] pattern) { + if( data == null || pattern == null) return -1; + + int[] failure = computeFailure(pattern); + + int j = 0; + + for( int i = start; i < stop; i++) { + while (j > 0 && ( pattern[j] != '*' && pattern[j] != data[i])) { + j = failure[j - 1]; + } + if (pattern[j] == '*' || pattern[j] == data[i]) { + j++; + } + if (j == pattern.length) { + return i - pattern.length + 1; + } + } + return -1; + } + + /** + * Computes the failure function using a boot-strapping process, + * where the pattern is matched against itself. + */ + private static int[] computeFailure(byte[] pattern) { + int[] failure = new int[pattern.length]; + + int j = 0; + for (int i = 1; i < pattern.length; i++) { + while (j>0 && pattern[j] != pattern[i]) { + j = failure[j - 1]; + } + if (pattern[j] == pattern[i]) { + j++; + } + failure[i] = j; + } + + return failure; + } +} // End of class KPM \ No newline at end of file diff --git a/javasrc/extfunc/org/etsi/its/extfunc/IItsExternalFunctionsProvider.java b/javasrc/extfunc/org/etsi/its/extfunc/IItsExternalFunctionsProvider.java index 84238dc8f..826fb0c75 100644 --- a/javasrc/extfunc/org/etsi/its/extfunc/IItsExternalFunctionsProvider.java +++ b/javasrc/extfunc/org/etsi/its/extfunc/IItsExternalFunctionsProvider.java @@ -4,10 +4,13 @@ */ package org.etsi.its.extfunc; +import org.etsi.ttcn.tci.BooleanValue; import org.etsi.ttcn.tci.CharstringValue; 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; /** * This interface provides the list of the TTCN-3 external function to be implemented @@ -119,4 +122,134 @@ public interface IItsExternalFunctionsProvider { ); public OctetstringValue xf_parseIpv6Address(final CharstringValue p_textIpv6Address); -} + + /** + * @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); + + /** + * @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); + + /** + * @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); + + /** + * @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); + + /** + * @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); + + /** + * @desc Check if a polygonal regin is inside another one + * @param p_parent The main polygonal region + * @param p_region The polygonal region to be included + * @return true on success, false otherwise + * @verdict Unchanged + */ + public BooleanValue fx_isPolygonalRegionInside(final RecordOfValue p_parent, final RecordOfValue p_region); + + /** + * @desc Check that the location is inside a circular region + * @param p_region The circular region to consider + * @param p_location The device location + * @return true on success, false otherwise + * @verdict Unchanged + */ + public BooleanValue fx_isLocationInsideCircularRegion(final RecordValue p_region, final RecordValue p_location); + + /** + * @desc Check that the location is inside a rectangular region + * @param p_region The rectangular region to consider + * @param p_location The device location + * @return true on success, false otherwise + * @verdict Unchanged + */ + public BooleanValue fx_isLocationInsideRectangularRegion(final RecordOfValue p_region, final RecordValue p_location); + + /** + * @desc Check that the location is inside a polygonal region + * @param p_region The polygonal region to consider + * @param p_location The device location + * @return true on success, false otherwise + * @verdict Unchanged + */ + public BooleanValue fx_isLocationInsidePolygonalRegion(final RecordOfValue p_region, final RecordValue p_location); + + /** + * @desc Check if the location is inside an identified region + * @param p_region The identified region to consider + * @param p_location The device location + * @return true on success, false otherwise + * @verdict Unchanged + */ + public BooleanValue fx_isLocationInsideIdentifiedRegion(final RecordValue p_region, final RecordValue p_location); + + /** + * @desc Convert a spacial coordinate from DMS to Dms + * @param p_degrees The degrees (D) + * @param p_minutes The minutes (M) + * @param p_seconds The seconds (S) + * @param p_latlon The latitude/longitude: (N|S|E|W) + * @return The decimal coordinate on success, 0.0, otherwise + * @verdict Unchanged + */ + public FloatValue fx_dms2dd(final IntegerValue p_degrees, final IntegerValue p_minutes, final FloatValue p_seconds, final OctetstringValue p_latlon); + + /** + * @desc Load in memory cache the certificates available in the specified directory + * @param p_rootDirectory Root directory to access to the certificates identified by the certificate ID + * @param p_configId A configuration identifier + * @return true on success, false otherwise + */ + public BooleanValue fx_loadCertificates(final CharstringValue p_rootDirectory, final CharstringValue p_configId); + + /** + * @desc Unload from memory cache the certificates + * @return true on success, false otherwise + */ + public BooleanValue fx_unloadCertificates(); + + /** + * @desc Read the specified certificate + * @param p_certificateId the certificate identifier + * @param p_certificate the expected certificate + * @return true on success, false otherwise + */ + public BooleanValue fx_readCertificate(final CharstringValue p_certificateId, OctetstringValue p_certificate); + + + /** + * @desc Read the private keys for the specified certificate + * @param p_keysId the keys identifier + * @param p_signingPrivateKey the signing private key + * @param p_encryptPrivateKey the encrypt private key + * @return true on success, false otherwise + */ + public BooleanValue fx_readPrivateKeys(final CharstringValue p_keysId, OctetstringValue p_signingPrivateKey, OctetstringValue p_encryptPrivateKey); + +} // End of interface IItsExternalFunctionsProvider diff --git a/javasrc/extfunc/org/etsi/its/extfunc/ItsExternalFunctionsProvider.java b/javasrc/extfunc/org/etsi/its/extfunc/ItsExternalFunctionsProvider.java index 38050719c..03374da03 100644 --- a/javasrc/extfunc/org/etsi/its/extfunc/ItsExternalFunctionsProvider.java +++ b/javasrc/extfunc/org/etsi/its/extfunc/ItsExternalFunctionsProvider.java @@ -13,15 +13,28 @@ import java.net.UnknownHostException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.logging.Logger; +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 @@ -29,8 +42,7 @@ import org.etsi.ttcn.tci.OctetstringValue; * See TTCN-3 modules LibItsGeoNetworking_Functions and LibItsCommon_Functions * */ -public class ItsExternalFunctionsProvider implements - IItsExternalFunctionsProvider { +public class ItsExternalFunctionsProvider implements IItsExternalFunctionsProvider { /** * Module version @@ -55,6 +67,11 @@ public class ItsExternalFunctionsProvider implements private static final long ITS_REF_TIME = 1072915200000L; + /** + * Reference to the ePassport files manager + */ + private ICertificatesIO _certCache = CertificatesIOFactory.getInstance(); + /** * Default ctor */ @@ -79,24 +96,20 @@ public class ItsExternalFunctionsProvider implements String datestr="01/01/2004 00:00:00"; DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss"); - IntegerValue now = _tcicdWrapper.getInteger(); + IntegerValue now = null; try { -// System.out.println(String.format("fx_getCurrentTime: now:%d, 2004:%d", System.currentTimeMillis(), ((java.util.Date)formatter.parse(datestr)).getTime())); -// System.out.println("Diff: " + (int)(System.currentTimeMillis() - ((java.util.Date)formatter.parse(datestr)).getTime())); - now.setBigInt( +// System.out.println("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 - ) + ByteHelper.longToByteArray(System.currentTimeMillis() - ((java.util.Date)formatter.parse(datestr)).getTime(), Long.SIZE / Byte.SIZE) ) ); } catch (ParseException e) { - now.setInt(0); + now = _tcicdWrapper.setInteger(0); } - _logger.exiting("ItsExternalFunctionsProvider", "fx_getCurrentTime", String.format("%10d", now.getInt())); + _logger.exiting("ItsExternalFunctionsProvider", "fx_getCurrentTime", String.format("%10d", _tcicdWrapper.getBigInteger(now))); return now; } // End of method fx_getCurrentTime @@ -121,24 +134,29 @@ public class ItsExternalFunctionsProvider implements public synchronized FloatValue fx_computeDistance( final IntegerValue p_latitudeA, final IntegerValue p_longitudeA, final IntegerValue p_latitudeB, final IntegerValue p_longitudeB) { - _logger.entering("ItsExternalFunctionsProvider", "fx_computeDistance", - String.format("%d, %d, %d, %d", p_latitudeA.getInt(), - p_longitudeA.getInt(), p_latitudeB.getInt(), - p_longitudeB.getInt())); +// _logger.entering("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(p_latitudeB.getInt()) - new Double( - p_latitudeA.getInt())) / 10000000; - double dlong = (new Double(p_longitudeB.getInt()) - new Double( - p_longitudeA.getInt())) / 10000000; + 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))); + long d = Math.round(Math.sqrt(Math.pow(dlat * rbis, 2) + Math.pow(dlong * rbis * Math.cos(dlat), 2))); dist.setFloat(d); - System.out.println("Distance: " + d); +// System.out.println("Distance: " + d); return dist; } // End of method fx_computeDistance @@ -169,21 +187,18 @@ public class ItsExternalFunctionsProvider implements final IntegerValue p_refLongitude, final IntegerValue p_distance, final IntegerValue p_orientation, IntegerValue p_latitude, IntegerValue p_longitude) { - _logger.entering( - "ItsExternalFunctionsProvider", - "fx_computePositionUsingDistance", - String.format("%d, %d", p_distance.getInt(), - p_orientation.getInt())); +// _logger.entering( +// "ItsExternalFunctionsProvider", +// "fx_computePositionUsingDistance", +// String.format("%d, %d", p_distance.getInteger(), +// p_orientation.getInteger())); - double angularD = new Double(p_distance.getInt()) / earthRadius; - double radHeading = new Double(p_orientation.getInt()) * Math.PI - / 180; + double angularD = new Double(_tcicdWrapper.getInteger(p_distance)) / earthRadius; + double radHeading = new Double(_tcicdWrapper.getInteger(p_orientation)) * Math.PI / 180; // Convert to rad - double lat1 = (new Double(p_refLatitude.getInt()) / 10000000) - * Math.PI / 180; - double long1 = (new Double(p_refLongitude.getInt()) / 10000000) - * Math.PI / 180; + 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)); @@ -200,8 +215,8 @@ public class ItsExternalFunctionsProvider implements long rlat2 = Math.round(lat2 * 10000000 / Math.PI * 180); long rlong2 = Math.round(long2 * 10000000 / Math.PI * 180); - p_latitude.setInt((int) rlat2); - p_longitude.setInt((int) rlong2); + p_latitude = _tcicdWrapper.setInteger((int) rlat2); + p_longitude = _tcicdWrapper.setInteger((int) rlong2); } // End of method fx_computePositionUsingDistance @@ -226,11 +241,14 @@ public class ItsExternalFunctionsProvider implements */ @Override public IntegerValue fx_computeGnTimestamp() { - - IntegerValue timestamp = _tcicdWrapper.getInteger(); - // /!\ ttwb specific - timestamp.setBigInt(new BigInteger(1, ByteHelper.longToByteArray(((System.currentTimeMillis() - ITS_REF_TIME) % (long)Math.pow(2,32)), 5))); + 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; } @@ -304,12 +322,11 @@ public class ItsExternalFunctionsProvider implements } // End of 'for' loop try { // Upper-Layer Packet Length (32bits) - pseudoheader.write(ByteHelper.intToByteArray( - p_payloadLength.getInt(), 4)); + 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) p_nextHdr.getInt()); + pseudoheader.write((byte) _tcicdWrapper.getInteger(p_nextHdr)); } catch (IOException e) { e.printStackTrace(); } @@ -371,4 +388,425 @@ public class ItsExternalFunctionsProvider implements 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) { + _logger.entering("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) { + _logger.entering("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 { + 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) { + _logger.entering("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 { + boolean ret = CryptoLib.verifyWithEcdsaNistp256WithSha256(toBeVerifiedData, ts103097SignatureEncodedAsByteArray, ecdsaNistp256PublicKeyX, ecdsaNistp256PublicKeyY); + result.setBoolean(ret); + } catch (Exception e) { + e.printStackTrace(); + } + + _logger.exiting("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) { + _logger.entering("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 + + _logger.exiting("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) { + _logger.entering("ItsExternalFunctionsProvider", "fx_isValidPolygonalRegion"); + + // Setup arguments + ArrayList polygonalArea = new ArrayList(); + for (int position = 0; position < p_region.getLength(); position++) { + RecordValue rv = (RecordValue) p_region.getField(position); + polygonalArea.add( + new WGS84( + _tcicdWrapper.getInteger((IntegerValue)(rv.getField("latitude"))), + _tcicdWrapper.getInteger((IntegerValue)(rv.getField("longitude"))) + )); + } // End of 'for' statement + + // Call Geodesic function + BooleanValue result = _tcicdWrapper.getBoolean(); + result.setBoolean(Positioning.getInstance().isValidPolygonArea(polygonalArea)); + + _logger.exiting("ItsExternalFunctionsProvider", "fx_isValidPolygonalRegion"); + return result; + } + + @Override + public BooleanValue fx_isPolygonalRegionInside(final RecordOfValue p_parent, final RecordOfValue p_region) { + _logger.entering("ItsExternalFunctionsProvider", "fx_isPolygonalRegionInside"); + + // Setup arguments + ArrayList parentArea = new ArrayList(); + for (int position = 0; position < p_parent.getLength(); position++) { + RecordValue rv = (RecordValue) p_parent.getField(position); + parentArea.add( + new WGS84( + _tcicdWrapper.getInteger((IntegerValue)(rv.getField("latitude"))), + _tcicdWrapper.getInteger((IntegerValue)(rv.getField("longitude"))) + )); + } // End of 'for' statement + ArrayList regionArea = new ArrayList(); + for (int position = 0; position < p_region.getLength(); position++) { + RecordValue rv = (RecordValue) p_region.getField(position); + regionArea.add( + new WGS84( + _tcicdWrapper.getInteger((IntegerValue)(rv.getField("latitude"))), + _tcicdWrapper.getInteger((IntegerValue)(rv.getField("longitude"))) + )); + } // End of 'for' statement + + // Call Geodesic function + BooleanValue result = _tcicdWrapper.getBoolean(); + result.setBoolean(Positioning.getInstance().isPolygonalRegionInside(parentArea, regionArea)); + + _logger.exiting("ItsExternalFunctionsProvider", "fx_isPolygonalRegionInside"); + return result; + } + + @Override + public BooleanValue fx_isLocationInsideCircularRegion(final RecordValue p_region, final RecordValue p_location) { + _logger.entering("ItsExternalFunctionsProvider", "fx_isLocationInsideCircularRegion"); + + // Setup arguments + RecordValue rv = (RecordValue)p_region.getField("center"); // Center + WGS84 center = new WGS84( + _tcicdWrapper.getInteger((IntegerValue)(rv.getField("latitude"))), + _tcicdWrapper.getInteger((IntegerValue)(rv.getField("longitude"))) + ); + int radius = _tcicdWrapper.getInteger((IntegerValue)p_region.getField("radius")); + WGS84 location = new WGS84( // Location + _tcicdWrapper.getInteger((IntegerValue)(p_location.getField("latitude"))), + _tcicdWrapper.getInteger((IntegerValue)(p_location.getField("longitude"))) + ); + + // Call Geodesic function + BooleanValue result = _tcicdWrapper.getBoolean(); + result.setBoolean(Positioning.getInstance().isLocationInsideCircularArea(location, center, radius)); + + _logger.exiting("ItsExternalFunctionsProvider", "fx_isLocationInsideCircularRegion"); + return result; + } + + @Override + public BooleanValue fx_isLocationInsideRectangularRegion(final RecordOfValue p_region, final RecordValue p_location) { + _logger.entering("ItsExternalFunctionsProvider", "fx_isLocationInsideRectangularRegion"); + + // Setup arguments + ArrayList< ArrayList > polygonalAreas = new ArrayList< ArrayList >(); + for (int position = 0; position < p_region.getLength(); position++) { + RecordValue rectangleArea = (RecordValue)p_region.getField(position); + // Retrieve corners + RecordValue rv = (RecordValue)rectangleArea.getField("northwest"); // Upper left corner + WGS84 upperLeftCorner = new WGS84( + (long)_tcicdWrapper.getInteger((IntegerValue)(rv.getField("latitude"))), + (long)_tcicdWrapper.getInteger((IntegerValue)(rv.getField("longitude"))) + ); + rv = (RecordValue)rectangleArea.getField("southeast"); // Lower right corner + WGS84 lowerRightCorner = new WGS84( + (long)_tcicdWrapper.getInteger((IntegerValue)(rv.getField("latitude"))), + (long) _tcicdWrapper.getInteger((IntegerValue)(rv.getField("longitude"))) + ); + // Build the polygonal area + ArrayList rectangularItem = new ArrayList(); + rectangularItem.add(upperLeftCorner); + rectangularItem.add( + new WGS84( + upperLeftCorner.getLatitude(), + lowerRightCorner.getLongitude(), + lowerRightCorner.getAltitude() + ) + ); + rectangularItem.add(lowerRightCorner); + rectangularItem.add( + new WGS84( + lowerRightCorner.getLatitude(), + upperLeftCorner.getLongitude(), + upperLeftCorner.getAltitude() + ) + ); + + polygonalAreas.add(rectangularItem); + } // End of 'for' statement + + WGS84 location = new WGS84( // Location + _tcicdWrapper.getInteger((IntegerValue)(p_location.getField("latitude"))), + _tcicdWrapper.getInteger((IntegerValue)(p_location.getField("longitude"))) + ); + + // Call Geodesic function + BooleanValue result = _tcicdWrapper.getBoolean(); + result.setBoolean(Positioning.getInstance().isLocationInsidePolygonalAreas(location, polygonalAreas)); + + _logger.exiting("ItsExternalFunctionsProvider", "fx_isLocationInsideRectangularRegion"); + return result; + } + + @Override + public BooleanValue fx_isLocationInsidePolygonalRegion(final RecordOfValue p_region, final RecordValue p_location) { + _logger.entering("ItsExternalFunctionsProvider", "fx_isLocationInsidePolygonalRegion"); + + // Setup arguments + ArrayList polygonalArea = new ArrayList(); + for (int position = 0; position < p_region.getLength(); position++) { + RecordValue rv = (RecordValue) p_region.getField(position); + polygonalArea.add( + new WGS84( + (long)_tcicdWrapper.getInteger((IntegerValue)(rv.getField("latitude"))), + (long)_tcicdWrapper.getInteger((IntegerValue)(rv.getField("longitude"))) + )); +// System.out.println("fx_isLocationInsidePolygonalRegion: add " + polygonalArea.get(polygonalArea.size() - 1)); + } // End of 'for' statement + WGS84 location = new WGS84( // Location + (long)_tcicdWrapper.getInteger((IntegerValue)(p_location.getField("latitude"))), + (long)_tcicdWrapper.getInteger((IntegerValue)(p_location.getField("longitude"))) + ); +// System.out.println("fx_isLocationInsidePolygonalRegion: location= " + location); + + // Call Geodesic function + BooleanValue result = _tcicdWrapper.getBoolean(); + result.setBoolean(Positioning.getInstance().isLocationInsidePolygonalArea(location, polygonalArea)); + + _logger.exiting("ItsExternalFunctionsProvider", "fx_isLocationInsidePolygonalRegion"); + return result; + } + + @Override + public BooleanValue fx_isLocationInsideIdentifiedRegion(final RecordValue p_region, final RecordValue p_location) { + _logger.entering("ItsExternalFunctionsProvider", "fx_isLocationInsideIdentifiedRegion"); + + // Setup arguments + int regionDictionary = ((EnumeratedValue) p_region.getField("region_dictionary")).getInt(); + int regionId = _tcicdWrapper.getInteger((IntegerValue)(p_region.getField("region_identifier"))); + long localRegion = _tcicdWrapper.getBigInteger((IntegerValue)(p_region.getField("local_region"))); + WGS84 location = new WGS84( // Location + _tcicdWrapper.getInteger((IntegerValue)(p_location.getField("latitude"))), + _tcicdWrapper.getInteger((IntegerValue)(p_location.getField("longitude"))) + ); + + // Call Geodesic function + BooleanValue result = _tcicdWrapper.getBoolean(); + result.setBoolean(Positioning.getInstance().isLocationInsideIdentifiedRegion(regionDictionary, regionId, localRegion, location)); + + _logger.exiting("ItsExternalFunctionsProvider", "fx_isLocationInsideIdentifiedRegion"); + return result; + } + + @Override + public FloatValue fx_dms2dd(final IntegerValue p_degrees, final IntegerValue p_minutes, final FloatValue p_seconds, final OctetstringValue p_latlon) { + _logger.entering("ItsExternalFunctionsProvider", "fx_dms2dd"); + + // Call Geodesic function + FloatValue result = _tcicdWrapper.getFloat(); + DMS location = new DMS( // Location + _tcicdWrapper.getInteger(p_degrees), + _tcicdWrapper.getInteger(p_minutes), + p_seconds.getFloat(), + (char)p_latlon.getOctet(0) + ); + result.setFloat((float) location.toDD()); + + _logger.exiting("ItsExternalFunctionsProvider", "fx_dms2dd"); + return result; + } + + /** + * @desc Load in memory cache the certificates available in the specified directory + * @param p_rootDirectory Root directory to access to the certificates identified by the certificate ID + * @param p_configId A configuration identifier + * @return true on success, false otherwise + */ + @Override + public BooleanValue fx_loadCertificates(final CharstringValue p_rootDirectory, final CharstringValue p_configId) { + + BooleanValue result = _tcicdWrapper.getBoolean(); + result.setBoolean(_certCache.loadCertificates(p_rootDirectory.getString(), p_configId.getString())); + + return result; + } + + /** + * @desc Unload from memory cache the certificates + * @return true on success, false otherwise + */ + @Override + public BooleanValue fx_unloadCertificates() { + + BooleanValue result = _tcicdWrapper.getBoolean(); + result.setBoolean(_certCache.unloadCertificates()); + + return result; + } + + /** + * @desc Read the specified certificate + * @param p_certificateId the certificate identifier + * @param p_certificate the expected certificate + * @return true on success, false otherwise + */ + @Override + public BooleanValue fx_readCertificate(final CharstringValue p_certificateId, OctetstringValue p_certificate) { + + BooleanValue result = _tcicdWrapper.getBoolean(); + ByteArrayOutputStream certificate = new ByteArrayOutputStream(); + result.setBoolean(_certCache.readCertificate(p_certificateId.getString(), certificate)); + + byte[] value = certificate.toByteArray(); + p_certificate.setLength(value.length); + if (value.length != 0) { + for (int i = 0; i < value.length; i++) { + p_certificate.setOctet(i, value[i]); + } // End 'for' statement + } + + return result; + } + + /** + * @desc Read the private keys for the specified certificate + * @param p_keysId the keys identifier + * @param p_signingPrivateKey the signing private key + * @param p_encryptPrivateKey the encrypt private key + * @return true on success, false otherwise + */ + @Override + public BooleanValue fx_readPrivateKeys(CharstringValue p_keysId, OctetstringValue p_signingPrivateKey, OctetstringValue p_encryptPrivateKey) { + + BooleanValue result = _tcicdWrapper.getBoolean(); + ByteArrayOutputStream signingPrivateKey = new ByteArrayOutputStream(); + ByteArrayOutputStream encryptPrivateKey = new ByteArrayOutputStream(); + result.setBoolean(_certCache.readPrivateKeys(p_keysId.getString(), signingPrivateKey, encryptPrivateKey)); + + byte[] value = signingPrivateKey.toByteArray(); + p_signingPrivateKey.setLength(value.length); + if (value.length != 0) { + for (int i = 0; i < value.length; i++) { + p_signingPrivateKey.setOctet(i, value[i]); + } // End 'for' statement + } + value = encryptPrivateKey.toByteArray(); + p_encryptPrivateKey.setLength(value.length); + if (value.length != 0) { + for (int i = 0; i < value.length; i++) { + p_encryptPrivateKey.setOctet(i, value[i]); + } // End 'for' statement + } + + return result; + } + } // End of class ExternalFunctions + diff --git a/javasrc/geodesic/org/etsi/geodesic/CountriesAreas.java b/javasrc/geodesic/org/etsi/geodesic/CountriesAreas.java new file mode 100644 index 000000000..6f7d676a8 --- /dev/null +++ b/javasrc/geodesic/org/etsi/geodesic/CountriesAreas.java @@ -0,0 +1,462 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.geodesic; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + + +public class CountriesAreas implements ICountriesAreas { + + /** + * Unique reference to this object + */ + private static ICountriesAreas Instance; + + /** + * The ISO-3166-1 region dictionary identifier + * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.25 IdentifiedRegion + */ + private final int Iso_3166_1 = 0; + + /** + * The United Nations region dictionary identifier + * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.25 IdentifiedRegion + */ + private final int Un_stats = 1; + + /** + * Reference to the Google JSon parser + */ + private JsonParser _jsonParser = null; + + /** + * Conversion from UN to ISO-3166 numerical code + * @see http://unstats.un.org/unsd/methods/m49/m49alphaf.htm + */ + private Map _un2iso3611; + + /** + * Conversion from ISO-3166 numerical code to alpha-2 code + * @see http://fr.wikipedia.org/wiki/ISO_3166-1 + */ + private Map _in2str4iso3611; + + /** + * Polygon areas for each country referenced by ISO 3166 + */ + private Map>> _countriesPolygons; + + /** + * Singleton pattern implementation + */ + public static ICountriesAreas getInstance() { + if (Instance == null) { + Instance = new CountriesAreas(); + Instance.initialise(); + } + + return Instance; + } + + private CountriesAreas() { + super(); + + _jsonParser = new JsonParser(); + + _countriesPolygons = new HashMap>>(); + + _in2str4iso3611 = new HashMap(); + _in2str4iso3611.put(new Integer(4), "AF"); + _in2str4iso3611.put(new Integer(8), "AL"); + _in2str4iso3611.put(new Integer(10), "AQ"); + _in2str4iso3611.put(new Integer(12), "DZ"); + _in2str4iso3611.put(new Integer(16), "AS"); + _in2str4iso3611.put(new Integer(20), "AD"); + _in2str4iso3611.put(new Integer(24), "AO"); + _in2str4iso3611.put(new Integer(28), "AG"); + _in2str4iso3611.put(new Integer(31), "AZ"); + _in2str4iso3611.put(new Integer(32), "AR"); + _in2str4iso3611.put(new Integer(36), "AU"); + _in2str4iso3611.put(new Integer(40), "AT"); + _in2str4iso3611.put(new Integer(44), "BS"); + _in2str4iso3611.put(new Integer(48), "BH"); + _in2str4iso3611.put(new Integer(50), "BD"); + _in2str4iso3611.put(new Integer(51), "AM"); + _in2str4iso3611.put(new Integer(52), "BB"); + _in2str4iso3611.put(new Integer(56), "BE"); + _in2str4iso3611.put(new Integer(60), "BM"); + _in2str4iso3611.put(new Integer(64), "BT"); + _in2str4iso3611.put(new Integer(68), "BO"); + _in2str4iso3611.put(new Integer(70), "BA"); + _in2str4iso3611.put(new Integer(72), "BA"); + _in2str4iso3611.put(new Integer(74), "BV"); + _in2str4iso3611.put(new Integer(76), "BR"); + _in2str4iso3611.put(new Integer(84), "BZ"); + _in2str4iso3611.put(new Integer(86), "IO"); + _in2str4iso3611.put(new Integer(90), "SB"); + _in2str4iso3611.put(new Integer(92), "VG"); + _in2str4iso3611.put(new Integer(96), "BN"); + _in2str4iso3611.put(new Integer(100), "BG"); + _in2str4iso3611.put(new Integer(104), "MM"); + _in2str4iso3611.put(new Integer(108), "BI"); + _in2str4iso3611.put(new Integer(112), "BY"); + _in2str4iso3611.put(new Integer(116), "KH"); + _in2str4iso3611.put(new Integer(120), "CM"); + _in2str4iso3611.put(new Integer(124), "CA"); + _in2str4iso3611.put(new Integer(132), "CV"); + _in2str4iso3611.put(new Integer(136), "CY"); + _in2str4iso3611.put(new Integer(140), "CF"); + _in2str4iso3611.put(new Integer(144), "LK"); + _in2str4iso3611.put(new Integer(148), "TD"); + _in2str4iso3611.put(new Integer(152), "CL"); + _in2str4iso3611.put(new Integer(156), "CN"); + _in2str4iso3611.put(new Integer(158), "TW"); + _in2str4iso3611.put(new Integer(162), "CX"); + _in2str4iso3611.put(new Integer(166), "CC"); + _in2str4iso3611.put(new Integer(170), "CO"); + _in2str4iso3611.put(new Integer(174), "KM"); + _in2str4iso3611.put(new Integer(175), "YT"); + _in2str4iso3611.put(new Integer(178), "CG"); + _in2str4iso3611.put(new Integer(180), "CD"); + _in2str4iso3611.put(new Integer(184), "CK"); + _in2str4iso3611.put(new Integer(188), "CR"); + _in2str4iso3611.put(new Integer(191), "HR"); + _in2str4iso3611.put(new Integer(192), "CU"); + _in2str4iso3611.put(new Integer(196), "CY"); + _in2str4iso3611.put(new Integer(203), "CZ"); + _in2str4iso3611.put(new Integer(204), "BJ"); + _in2str4iso3611.put(new Integer(208), "DK"); + _in2str4iso3611.put(new Integer(212), "DM"); + _in2str4iso3611.put(new Integer(214), "DO"); + _in2str4iso3611.put(new Integer(218), "EC"); + _in2str4iso3611.put(new Integer(222), "SV"); + _in2str4iso3611.put(new Integer(226), "GQ"); + _in2str4iso3611.put(new Integer(231), "ET"); + _in2str4iso3611.put(new Integer(232), "ER"); + _in2str4iso3611.put(new Integer(233), "EE"); + _in2str4iso3611.put(new Integer(234), "FO"); + _in2str4iso3611.put(new Integer(238), "FK"); + _in2str4iso3611.put(new Integer(239), "GS"); + _in2str4iso3611.put(new Integer(242), "FJ"); + _in2str4iso3611.put(new Integer(246), "FI"); + _in2str4iso3611.put(new Integer(248), "AX"); + _in2str4iso3611.put(new Integer(250), "FR"); + _in2str4iso3611.put(new Integer(254), "GF"); + _in2str4iso3611.put(new Integer(258), "PF"); + _in2str4iso3611.put(new Integer(260), "TF"); + _in2str4iso3611.put(new Integer(262), "DJ"); + _in2str4iso3611.put(new Integer(266), "GA"); + _in2str4iso3611.put(new Integer(268), "GE"); + _in2str4iso3611.put(new Integer(270), "GM"); + _in2str4iso3611.put(new Integer(275), "PS"); + _in2str4iso3611.put(new Integer(276), "DE"); + _in2str4iso3611.put(new Integer(288), "GH"); + _in2str4iso3611.put(new Integer(292), "GI"); + _in2str4iso3611.put(new Integer(296), "KI"); + _in2str4iso3611.put(new Integer(300), "GR"); + _in2str4iso3611.put(new Integer(304), "GL"); + _in2str4iso3611.put(new Integer(308), "GD"); + _in2str4iso3611.put(new Integer(312), "GP"); + _in2str4iso3611.put(new Integer(316), "GU"); + _in2str4iso3611.put(new Integer(320), "GT"); + _in2str4iso3611.put(new Integer(324), "GI"); + _in2str4iso3611.put(new Integer(328), "GY"); + _in2str4iso3611.put(new Integer(332), "HT"); + _in2str4iso3611.put(new Integer(334), "HM"); + _in2str4iso3611.put(new Integer(336), "VA"); + _in2str4iso3611.put(new Integer(340), "HN"); + _in2str4iso3611.put(new Integer(344), "HK"); + _in2str4iso3611.put(new Integer(348), "HU"); + _in2str4iso3611.put(new Integer(352), "IS"); + _in2str4iso3611.put(new Integer(356), "IN"); + _in2str4iso3611.put(new Integer(360), "ID"); + _in2str4iso3611.put(new Integer(364), "IR"); + _in2str4iso3611.put(new Integer(368), "IR"); + _in2str4iso3611.put(new Integer(372), "IE"); + _in2str4iso3611.put(new Integer(376), "IL"); + _in2str4iso3611.put(new Integer(380), "IT"); + _in2str4iso3611.put(new Integer(384), "CI"); + _in2str4iso3611.put(new Integer(388), "JM"); + _in2str4iso3611.put(new Integer(392), "JP"); + _in2str4iso3611.put(new Integer(398), "KZ"); + _in2str4iso3611.put(new Integer(400), "JO"); + _in2str4iso3611.put(new Integer(404), "KE"); + _in2str4iso3611.put(new Integer(408), "KP"); + _in2str4iso3611.put(new Integer(410), "KR"); + _in2str4iso3611.put(new Integer(414), "KW"); + _in2str4iso3611.put(new Integer(417), "KG"); + _in2str4iso3611.put(new Integer(418), "LA"); + _in2str4iso3611.put(new Integer(422), "LB"); + _in2str4iso3611.put(new Integer(426), "LS"); + _in2str4iso3611.put(new Integer(428), "LV"); + _in2str4iso3611.put(new Integer(430), "LR"); + _in2str4iso3611.put(new Integer(434), "LY"); + _in2str4iso3611.put(new Integer(438), "LI"); + _in2str4iso3611.put(new Integer(440), "LT"); + _in2str4iso3611.put(new Integer(442), "LU"); + _in2str4iso3611.put(new Integer(446), "MO"); + _in2str4iso3611.put(new Integer(450), "MG"); + _in2str4iso3611.put(new Integer(454), "MW"); + _in2str4iso3611.put(new Integer(458), "MY"); + _in2str4iso3611.put(new Integer(462), "MV"); + _in2str4iso3611.put(new Integer(466), "ML"); + _in2str4iso3611.put(new Integer(470), "MT"); + _in2str4iso3611.put(new Integer(474), "MQ"); + _in2str4iso3611.put(new Integer(478), "MR"); + _in2str4iso3611.put(new Integer(480), "MU"); + _in2str4iso3611.put(new Integer(484), "MX"); + _in2str4iso3611.put(new Integer(492), "MC"); + _in2str4iso3611.put(new Integer(496), "MN"); + _in2str4iso3611.put(new Integer(498), "MD"); + _in2str4iso3611.put(new Integer(499), "ME"); + _in2str4iso3611.put(new Integer(500), "MS"); + _in2str4iso3611.put(new Integer(504), "MA"); + _in2str4iso3611.put(new Integer(508), "MZ"); + _in2str4iso3611.put(new Integer(512), "OM"); + _in2str4iso3611.put(new Integer(516), "NA"); + _in2str4iso3611.put(new Integer(520), "NR"); + _in2str4iso3611.put(new Integer(524), "NP"); + _in2str4iso3611.put(new Integer(528), "NL"); + _in2str4iso3611.put(new Integer(531), "CW"); + _in2str4iso3611.put(new Integer(533), "AW"); + _in2str4iso3611.put(new Integer(534), "SX"); + _in2str4iso3611.put(new Integer(535), "BQ"); + _in2str4iso3611.put(new Integer(540), "NC"); + _in2str4iso3611.put(new Integer(548), "VU"); + _in2str4iso3611.put(new Integer(554), "NZ"); + _in2str4iso3611.put(new Integer(558), "NI"); + _in2str4iso3611.put(new Integer(562), "NE"); + _in2str4iso3611.put(new Integer(566), "NG"); + _in2str4iso3611.put(new Integer(570), "NU"); + _in2str4iso3611.put(new Integer(574), "NF"); + _in2str4iso3611.put(new Integer(578), "NO"); + _in2str4iso3611.put(new Integer(580), "MP"); + _in2str4iso3611.put(new Integer(581), "UM"); + _in2str4iso3611.put(new Integer(583), "FM"); + _in2str4iso3611.put(new Integer(584), "MH"); + _in2str4iso3611.put(new Integer(585), "PW"); + _in2str4iso3611.put(new Integer(586), "PK"); + _in2str4iso3611.put(new Integer(591), "PA"); + _in2str4iso3611.put(new Integer(598), "PG"); + _in2str4iso3611.put(new Integer(600), "PY"); + _in2str4iso3611.put(new Integer(604), "PE"); + _in2str4iso3611.put(new Integer(608), "PH"); + _in2str4iso3611.put(new Integer(612), "PN"); + _in2str4iso3611.put(new Integer(616), "PL"); + _in2str4iso3611.put(new Integer(620), "PT"); + _in2str4iso3611.put(new Integer(624), "GW"); + _in2str4iso3611.put(new Integer(626), "TL"); + _in2str4iso3611.put(new Integer(630), "PR"); + _in2str4iso3611.put(new Integer(634), "QA"); + _in2str4iso3611.put(new Integer(638), "RE"); + _in2str4iso3611.put(new Integer(642), "RO"); + _in2str4iso3611.put(new Integer(643), "RU"); + _in2str4iso3611.put(new Integer(646), "RW"); + _in2str4iso3611.put(new Integer(652), "BL"); + _in2str4iso3611.put(new Integer(654), "SH"); + _in2str4iso3611.put(new Integer(659), "KN"); + _in2str4iso3611.put(new Integer(660), "AI"); + _in2str4iso3611.put(new Integer(662), "LC"); + _in2str4iso3611.put(new Integer(663), "MF"); + _in2str4iso3611.put(new Integer(666), "PM"); + _in2str4iso3611.put(new Integer(670), "VC"); + _in2str4iso3611.put(new Integer(674), "SM"); + _in2str4iso3611.put(new Integer(678), "ST"); + _in2str4iso3611.put(new Integer(682), "SA"); + _in2str4iso3611.put(new Integer(686), "SN"); + _in2str4iso3611.put(new Integer(688), "RS"); + _in2str4iso3611.put(new Integer(690), "SC"); + _in2str4iso3611.put(new Integer(694), "SL"); + _in2str4iso3611.put(new Integer(702), "SG"); + _in2str4iso3611.put(new Integer(703), "SK"); + _in2str4iso3611.put(new Integer(704), "VN"); + _in2str4iso3611.put(new Integer(705), "SI"); + _in2str4iso3611.put(new Integer(706), "SO"); + _in2str4iso3611.put(new Integer(710), "ZA"); + _in2str4iso3611.put(new Integer(716), "ZW"); + _in2str4iso3611.put(new Integer(724), "ES"); + _in2str4iso3611.put(new Integer(728), "SS"); + _in2str4iso3611.put(new Integer(729), "SD"); + _in2str4iso3611.put(new Integer(732), "EH"); + _in2str4iso3611.put(new Integer(740), "SR"); + _in2str4iso3611.put(new Integer(744), "SJ"); + _in2str4iso3611.put(new Integer(748), "SZ"); + _in2str4iso3611.put(new Integer(752), "SE"); + _in2str4iso3611.put(new Integer(756), "CH"); + _in2str4iso3611.put(new Integer(760), "SY"); + _in2str4iso3611.put(new Integer(762), "TJ"); + _in2str4iso3611.put(new Integer(764), "TH"); + _in2str4iso3611.put(new Integer(768), "TG"); + _in2str4iso3611.put(new Integer(772), "TK"); + _in2str4iso3611.put(new Integer(776), "TO"); + _in2str4iso3611.put(new Integer(780), "TT"); + _in2str4iso3611.put(new Integer(784), "AE"); + _in2str4iso3611.put(new Integer(788), "TN"); + _in2str4iso3611.put(new Integer(792), "TR"); + _in2str4iso3611.put(new Integer(795), "TM"); + _in2str4iso3611.put(new Integer(796), "TC"); + _in2str4iso3611.put(new Integer(798), "TV"); + _in2str4iso3611.put(new Integer(800), "UG"); + _in2str4iso3611.put(new Integer(804), "UA"); + _in2str4iso3611.put(new Integer(807), "MK"); + _in2str4iso3611.put(new Integer(818), "EG"); + _in2str4iso3611.put(new Integer(826), "GB"); + _in2str4iso3611.put(new Integer(831), "GG"); + _in2str4iso3611.put(new Integer(832), "JE"); + _in2str4iso3611.put(new Integer(833), "IM"); + _in2str4iso3611.put(new Integer(834), "TZ"); + _in2str4iso3611.put(new Integer(840), "US"); + _in2str4iso3611.put(new Integer(850), "VI"); + _in2str4iso3611.put(new Integer(854), "BF"); + _in2str4iso3611.put(new Integer(858), "UY"); + _in2str4iso3611.put(new Integer(860), "UZ"); + _in2str4iso3611.put(new Integer(862), "VE"); + _in2str4iso3611.put(new Integer(876), "WF"); + _in2str4iso3611.put(new Integer(882), "WS"); + _in2str4iso3611.put(new Integer(887), "YE"); + _in2str4iso3611.put(new Integer(894), "ZM"); + + _un2iso3611 = _in2str4iso3611; // Until today, both tables are identical + + } // End of constructor + + @Override + public boolean initialise() { + try { + // Load JSon countries areas and parse it + RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); + Map systemProperties = runtimeBean.getSystemProperties(); + String fileName = systemProperties.get("user.dir") + systemProperties.get("file.separator") + "ne-countries-50m.json"; + BufferedReader in = new BufferedReader(new FileReader(new File(fileName))); + StringBuilder str = new StringBuilder(); + String lineSeparator = System.getProperty("line.separator"); + String line; + while ((line = in.readLine()) != null ) { + str.append(line); + str.append(lineSeparator); + } // End of 'while' statement + try { + parseLine(str.toString()); + } catch (JsonSyntaxException e) { + e.printStackTrace(); + } + in.close(); + + return true; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return false; + } + + /** + * + * @param p_stringToParse The JSon file to parse + * @see http://geojson.org/geojson-spec.html + * @see http://ckan.it.ox.ac.uk/fr/dataset/geojson-by-country-code + */ + private void parseLine(final String p_stringToParse) { + JsonElement jelement = _jsonParser.parse(p_stringToParse); + if (jelement != null) { + JsonObject jobj = jelement.getAsJsonObject(); + if (jobj != null) { + JsonArray jarray = jobj.getAsJsonArray("features"); + for (int i = 0; i < jarray.size(); i++) { + JsonObject properties = jarray.get(i).getAsJsonObject().getAsJsonObject("properties"); + String regionId = properties.getAsJsonPrimitive("iso_a2").getAsString(); + JsonObject geometry = jarray.get(i).getAsJsonObject().getAsJsonObject("geometry"); + String type = geometry.getAsJsonPrimitive("type").getAsString(); + _countriesPolygons.put(regionId, new ArrayList>()); + if (type.equalsIgnoreCase("Polygon") ) { + ArrayList points = new ArrayList(); + JsonArray coordinates = geometry.getAsJsonArray("coordinates").get(0).getAsJsonArray(); + for (int j = 0; j < coordinates.size(); j++) { + points.add( + new WGS84( + coordinates.get(j).getAsJsonArray().get(1).getAsDouble(), + coordinates.get(j).getAsJsonArray().get(0).getAsDouble(), + 0 + ) + ); + } // End of 'for' statement + _countriesPolygons.get(regionId).add(points); + } else if (geometry.getAsJsonPrimitive("type").getAsString().equalsIgnoreCase("MultiPolygon")) { + ArrayList points = new ArrayList(); + JsonArray coordinates = geometry.getAsJsonArray("coordinates"); + for (int j = 0; j < coordinates.size(); j++) { + JsonArray subCoordinates = coordinates.get(j).getAsJsonArray(); + for (int k = 0; k < subCoordinates.size(); k++) { + JsonArray subSubCoordinates = subCoordinates.get(k).getAsJsonArray(); + for (int l = 0; l < subSubCoordinates.size(); l++) { + points.add( + new WGS84( + subSubCoordinates.get(l).getAsJsonArray().get(1).getAsDouble(), + subSubCoordinates.get(l).getAsJsonArray().get(0).getAsDouble(), + 0 + ) + ); + } // End of 'for' statement + } // End of 'for' statement + _countriesPolygons.get(regionId).add(points); + } // End of 'for' statement + } else if (geometry.getAsJsonPrimitive("type").getAsString().equalsIgnoreCase("LineString")) { + // TODO To be continued + } else if (geometry.getAsJsonPrimitive("type").getAsString().equalsIgnoreCase("MultiLineString")) { + // TODO To be continued + } + } // End of 'for' statement + } + } + } + + @Override + public boolean isLocationInsideIdentifiedRegion(final int p_regionDictionary, final int p_regionId, final long p_localRegion, final WGS84 p_location) { +// System.out.println(">>> CountriesAreas.isLocationInsideIdentifiedRegion: " + p_regionDictionary + ", " + p_regionId + ", " + p_localRegion + ", " + p_location); + + boolean result = false; + if (p_regionDictionary == Iso_3166_1) { + if (_in2str4iso3611.containsKey(p_regionId)) { + result = process(_in2str4iso3611.get(p_regionId), p_localRegion, p_location); + } // else, error + } else if (p_regionDictionary == Un_stats) { + if (_un2iso3611.containsKey(p_regionId)) { + result = process(_in2str4iso3611.get(p_regionId), p_localRegion, p_location); + } // else, error + } // else, error + + return result; + } + + public boolean process(final String p_regionId, final long p_localRegion, final WGS84 p_location) { +// System.out.println(">>> CountriesAreas.process: " + p_regionId + ", " + p_localRegion + ", " + p_location); + + if (_countriesPolygons.containsKey(p_regionId)) { + ArrayList> areas = _countriesPolygons.get(p_regionId); + return Positioning.getInstance().isLocationInsidePolygonalAreas(p_location, areas); + } + + return false; + } + +} // End of class CountriesAreas diff --git a/javasrc/geodesic/org/etsi/geodesic/DMS.java b/javasrc/geodesic/org/etsi/geodesic/DMS.java new file mode 100644 index 000000000..0577d90ef --- /dev/null +++ b/javasrc/geodesic/org/etsi/geodesic/DMS.java @@ -0,0 +1,55 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.geodesic; + +public class DMS { + + private int _degrees = Integer.MAX_VALUE; + + private int _minutes = Integer.MAX_VALUE; + + private double _seconds = Double.NaN; + + private char _latlon = (char)0x00; + + private double _wgs84 = Double.NaN; + + /** + * @desc Constructor + * @param p_degrees The degrees (D) + * @param p_minutes The minutes (M) + * @param p_seconds The seconds (S) + * @param p_latlon The latitude/longitude: (N|S|E|W) + */ + public DMS(final int p_degrees, final int p_minutes, final double p_seconds, final char p_latlon) { + setValue(p_degrees, p_minutes, p_seconds, p_latlon); + } // End of DMS ctor + + /** + * @desc Update location + * @param p_degrees The degrees (D) + * @param p_minutes The minutes (M) + * @param p_seconds The seconds (S) + * @param p_latlon The latitude/longitude: (N|S|E|W) + */ + public void setValue(final int p_degrees, final int p_minutes, final double p_seconds, final char p_latlon) { + _degrees = p_degrees; + _minutes = p_minutes; + _seconds = p_seconds; + _latlon = p_latlon; + + _wgs84 = + (double)p_degrees + + (double)p_minutes / 60 + + (double)p_seconds / 3600; + if ((p_latlon == 'W') || (p_latlon == 'S')) _wgs84 *= -1.0; + } + + public double toDD() { + return _wgs84; + } + +} // End of class DMS diff --git a/javasrc/geodesic/org/etsi/geodesic/ICountriesAreas.java b/javasrc/geodesic/org/etsi/geodesic/ICountriesAreas.java new file mode 100644 index 000000000..8b0f3caf5 --- /dev/null +++ b/javasrc/geodesic/org/etsi/geodesic/ICountriesAreas.java @@ -0,0 +1,27 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.geodesic; + +public interface ICountriesAreas { + + /** + * @desc Initialise the object + * @return true on success, false otherwise + */ + public boolean initialise(); + + /** + * @desc Check if a location is inside a predefined geographic region determined by the region dictionary and the region identifier + * @param p_regionDictionary The region dictionary + * @param p_regionId The region identifier + * @param p_localRegion The whole region. 0 if the whole region is meant + * @param p_location The location to be checked + * @return true on success, false otherwise + * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.25 IdentifiedRegion + */ + public boolean isLocationInsideIdentifiedRegion(final int p_regionDictionary, final int p_regionId, final long p_localRegion, final WGS84 p_location); + +} // End of interface ICountriesAreas diff --git a/javasrc/geodesic/org/etsi/geodesic/IPositioning.java b/javasrc/geodesic/org/etsi/geodesic/IPositioning.java new file mode 100644 index 000000000..de8776643 --- /dev/null +++ b/javasrc/geodesic/org/etsi/geodesic/IPositioning.java @@ -0,0 +1,71 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.geodesic; + +import java.util.ArrayList; + +public interface IPositioning { + + /** + * @desc Check that the location is inside an elliptic area + * @param p_location The device location + * @param p_ellipticArea The circular area to consider + * @return true on success, false otherwise + */ + public boolean isLocationInsideEllipticArea(final WGS84 p_location, final ArrayList p_ellipticArea); + + /** + * @desc Check that the location is inside a polygonal area + * @param p_location The device location + * @param p_polygonalArea The polygonal area to consider + * @return true on success, false otherwise + */ + public boolean isLocationInsidePolygonalArea(final WGS84 p_location, final ArrayList p_polygonalArea); + + /** + * @desc Check that the location is inside a list of polygonal areas + * @param p_location The device location + * @param p_polygonalAreas The list of polygonal areas to consider + * @return true on success, false otherwise + */ + public boolean isLocationInsidePolygonalAreas(final WGS84 p_location, final ArrayList< ArrayList > p_polygonalAreas); + + /** + * @desc Check that the location is inside a circular area + * @param p_region The circular area to consider + * @param p_center The circle center position + * @param p_radius The circle radius + * @return true on success, false otherwise + */ + public boolean isLocationInsideCircularArea(final WGS84 p_location, final WGS84 p_center, final int p_radius); + + /** + * @desc Check if the polygonal area is valid (neither self-intersections nor holes) + * @param p_polygonalArea The polygonal area to consider + * @return true on success, false otherwise + */ + public boolean isValidPolygonArea(final ArrayList p_polygonalArea); + + /** + * @desc Check if the location is inside an identified region + * @param p_regionDictionary + * @param p_regionId + * @param p_localRegion + * @param p_location + * @return true on success, false otherwise + */ + boolean isLocationInsideIdentifiedRegion(final int p_regionDictionary, final int p_regionId, final long p_localRegion, final WGS84 p_location); + + /** + * @desc Check if a polygonal regin is inside another one + * @param p_parent The main polygonal region + * @param p_region The polygonal region to be included + * @return true on success, false otherwise + * @verdict Unchanged + */ + public boolean isPolygonalRegionInside(final ArrayList p_parentArea, final ArrayList p_regionArea); + +} // End of interface Positioning diff --git a/javasrc/geodesic/org/etsi/geodesic/Positioning.java b/javasrc/geodesic/org/etsi/geodesic/Positioning.java new file mode 100644 index 000000000..904cf1922 --- /dev/null +++ b/javasrc/geodesic/org/etsi/geodesic/Positioning.java @@ -0,0 +1,173 @@ +package org.etsi.geodesic; + +import java.util.ArrayList; + +/** + * @desc + * @see To validate GPS location: http://www.gps-coordinates.net + */ +public class Positioning implements IPositioning { + + public static double TWOPI = 2 * Math.PI; + + /** + * Unique reference to this object + */ + private static IPositioning Instance; + + /** + * Singleton pattern implementation + */ + public static IPositioning getInstance() { + if (Instance == null) { + Instance = new Positioning(); + } + + return Instance; + } + + /** + * Private constructor required for Singleton pattern implementation + */ + private Positioning() { + + } + + @Override + public boolean isLocationInsideEllipticArea(final WGS84 p_location, final ArrayList p_ellipticArea) { +// System.out.println(">>> Positioning.isLocationInsideEllipticArea: " + p_location); + + // TODO: implement it + // Do not forget aboout passing throw 0 meridian + return false; + } + + @Override + public boolean isLocationInsidePolygonalArea(final WGS84 p_location, final ArrayList p_polygonalArea) { +// System.out.println(">>> Positioning.isLocationInsidePolygonalArea: " + p_location + ", " + p_polygonalArea); + + // TODO: Check passing throw 0 meridian and Equador + + double angle = 0; + int poleNum = p_polygonalArea.size(); + for (int index = 0; index < poleNum; index++) { + WGS84 delta1 = new WGS84( + p_polygonalArea.get(index).getLatitude() - p_location.getLatitude(), + p_polygonalArea.get(index).getLongitude() - p_location.getLongitude(), + 0 + ); + WGS84 delta2 = new WGS84( + p_polygonalArea.get((index + 1) % poleNum).getLatitude() - p_location.getLatitude(), + p_polygonalArea.get((index + 1) % poleNum).getLongitude() - p_location.getLongitude(), + 0 + ); + angle += calcAngle(delta1, delta2); + } // End of 'for' statement + +// System.out.println("<<< Positioning.isLocationInsidePolygonalArea: " + (boolean)((Math.abs(angle) < Math.PI) ? false : true)); + return (boolean)((Math.abs(angle) < Math.PI) ? false : true); + } + + @Override + public boolean isLocationInsidePolygonalAreas(final WGS84 p_location, final ArrayList< ArrayList > p_polygonalAreas) { +// System.out.println(">>> Positioning.isLocationInsidePolygonalAreas: " + p_location); + + for (int index = 0; index < p_polygonalAreas.size(); index++) { + if (isLocationInsidePolygonalArea(p_location, p_polygonalAreas.get(index))) { + return true; + } + } // End of 'for' statement + + return false; // Not found + } + + @Override + public boolean isLocationInsideCircularArea(final WGS84 p_location, final WGS84 p_center, final int p_radius) { +// System.out.println(">>> Positioning.isLocationInsideCircularArea: " + p_location + ", " + p_center + ", " + p_radius); + + // TODO: Check passing throw 0 meridian and Equador + + double theta = p_center.getLongitude() - p_location.getLongitude(); + double distance = + Math.sin(dd2rad(p_center.getLatitude())) * Math.sin(dd2rad(p_location.getLatitude())) + + Math.cos(dd2rad(p_center.getLatitude())) * Math.cos(dd2rad(p_location.getLatitude())) * Math.cos(dd2rad(theta)); + distance = rad2dd(Math.acos(distance)); + distance *= 60 * 1.1515 * 1.609344 /*Kilometers*/; +// System.out.println("Positioning.isLocationInsideCircularArea: distance=" + distance); + +// System.out.println("<<< Positioning.isLocationInsideCircularArea: " + (boolean)(distance <= (p_radius / 1000.0))); + return (boolean)(distance <= (p_radius / 1000.0)); + } + + @Override + public boolean isValidPolygonArea(final ArrayList p_polygonalArea) { +// System.out.println(">>> Positioning.isValidPolygonArea"); + + // Check if polygon coordinates are valid + for (int i = 0; i < p_polygonalArea.size(); i++) { + if (!p_polygonalArea.get(i).isValidPosition()) { + return false; + } + } + + return true; + } + + @Override + public boolean isLocationInsideIdentifiedRegion(final int p_regionDictionary, final int p_regionId, final long p_localRegion, final WGS84 p_location) { +// System.out.println(">>> Positioning.isLocationInsideIdentifiedRegion: " + p_regionDictionary + ", " + p_regionId + ", " + p_localRegion + ", " + p_location); + + return CountriesAreas.getInstance().isLocationInsideIdentifiedRegion(p_regionDictionary, p_regionId, p_localRegion, p_location); + } + + @Override + public boolean isPolygonalRegionInside(final ArrayList p_parentArea, final ArrayList p_regionArea) { +// System.out.println(">>> Positioning.isPolygonalRegionInside: " + p_parentArea + ", " + p_regionArea); + + for (int i = 0; i < p_regionArea.size(); i++) { + if (!isLocationInsidePolygonalArea(p_regionArea.get(i), p_parentArea)) { + return false; + } + } // End of 'for' statement + + return true; + } + + private double calcAngle(final WGS84 p_origin, final WGS84 p_end) { +// System.out.println(">>> calcAngle: " + p_origin.getLatitude() + " - " + p_origin.getLongitude() + " - " + p_end.getLatitude() + " - " + p_end.getLongitude()); + double theta1 = Math.atan2(p_origin.getLatitude(), p_origin.getLongitude()); +// System.out.println("Angle2D: theta1=" + theta1); + double theta2 = Math.atan2(p_end.getLatitude(), p_end.getLongitude()); +// System.out.println("Angle2D: theta2=" + theta2); + double dtheta = theta2 - theta1; +// System.out.println("calcAngle: dtheta" + dtheta); + while (dtheta > Math.PI) { + dtheta -= TWOPI; + } // End of 'while' statement + while (dtheta < -Math.PI) { + dtheta += TWOPI; + } // End of 'while' statement + +// System.out.println("<<< calcAngle: " + dtheta); + return dtheta; + } + + /** + * @desc Convert a decimal degrees value into a decimal radian + * @param p_decimalDegrees The value to convert + * @return The converted value in radians + */ + private double dd2rad(final double p_decimalDegrees) { + return p_decimalDegrees * Math.PI / 180; + } + + /** + * @desc Convert a decimal radians value into a decimal degrees + * @param p_decimalRadians The value to convert + * @return The converted value in degrees + */ + private double rad2dd(final double p_decimalRadians) { + return p_decimalRadians * 180.0 / Math.PI; + } + +} // End of class Positioning diff --git a/javasrc/geodesic/org/etsi/geodesic/WGS84.java b/javasrc/geodesic/org/etsi/geodesic/WGS84.java new file mode 100644 index 000000000..713febc37 --- /dev/null +++ b/javasrc/geodesic/org/etsi/geodesic/WGS84.java @@ -0,0 +1,112 @@ +/** + * @author ETSI / STF481 / Yann Garcia + * @version $URL$ + * $Id$ + */ +package org.etsi.geodesic; + +public class WGS84 { + + /** Longitude of the location */ + private double _longitude = Double.NaN; + + /** Latitude of the location */ + private double _latitude = Double.NaN; + + /** Altitude of the location */ + private double _altitude = Double.NaN; + + private int _longitudeD = Integer.MAX_VALUE; + + private int _longitudeM = Integer.MAX_VALUE; + + private double _longitudeS = Double.NaN; + + private int _latitudeD = Integer.MAX_VALUE; + + private int _latitudeM = Integer.MAX_VALUE; + + private double _latitudeS = Double.NaN; + + /** Heading of the location */ +// private double _heading = Double.NaN; + + /** + * @desc Constructor + * @param p_longitude Longitude of the location + * @param p_latitude Latitude of the location + * @param p_altitude Altitude of the location + */ + public WGS84(final double p_latitude, final double p_longitude, final double p_altitude) { + setValue(p_latitude, p_longitude, p_altitude); + } // End of WGS84 ctor + + /** + * Constructor used to convert WGSLatitude/WGSLongitude value into decimal degrees value + * @param p_latitude Latiude integer value (significand length shall be 7 digits length) + * @param p_longitude Longitude integer value (significand length shall 6 digits length) + */ + public WGS84(final long p_latitude, final long p_longitude) { + setValue( + (double)p_latitude / 10000000, + (double)p_longitude / 1000000, + 0.0 + ); + } // End of WGS84 ctor + + /** + * @desc Update location + * @param p_longitude Longitude of the location + * @param p_latitude Latitude of the location + * @param p_altitude Altitude of the location + */ + public void setValue(final double p_latitude, final double p_longitude, final double p_altitude) { + _latitude = p_latitude; + _latitudeD = (int)p_latitude; // Truncate the decimals + double dv = (p_latitude - _latitudeD) * 60; + _latitudeM = (int)dv; + _latitudeS = (dv - _latitudeM) * 60; + + _longitude = p_longitude; + _longitudeD = (int)p_longitude; // Truncate the decimals + dv = (p_longitude - _longitudeD) * 60; + _longitudeM = (int)dv; + _longitudeS = (dv - _longitudeM) * 60; + + _altitude = p_altitude; + } + + public double getLongitude() { + return _longitude; + } + + public double getLatitude() { + return _latitude; + } + + public double getAltitude() { + return _altitude; + } + + public boolean isValidPosition() { + if ((_latitude > -90) && (_latitude < 90) && (_longitude > -180) && (_longitude < 180)) { + return true; + } + + return false; + } + + public String toDMS() { + return String.format("WGS84: l=%s°$s'%s'', L=%s°$s'%s'', A=%s", + String.valueOf(_latitudeD), String.valueOf(_latitudeM), String.valueOf(_latitudeS), + String.valueOf(_longitudeD), String.valueOf(_longitudeM), String.valueOf(_longitudeS), + String.valueOf(_altitude) + ); + } + + @Override + public String toString() { + return String.format("WGS84: lat=%s, lon=%s, alt=%s", String.valueOf(_latitude), String.valueOf(_longitude), String.valueOf(_altitude)); + } + +} // End of class WGS84 diff --git a/javasrc/tool/org/etsi/its/tool/elvior/BuiltInCodec.java b/javasrc/tool/org/etsi/its/tool/elvior/BuiltInCodec.java new file mode 100644 index 000000000..64bd52ff5 --- /dev/null +++ b/javasrc/tool/org/etsi/its/tool/elvior/BuiltInCodec.java @@ -0,0 +1,161 @@ +package org.etsi.its.tool.elvior; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.elvior.ttcn.tritci.TciProvider; +import org.elvior.ttcn.tritci.TriMessageEx; +import org.elvior.ttcn.tritci.TriProvider; +import org.etsi.common.ByteHelper; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.TciCDProvided; +import org.etsi.ttcn.tci.Type; +import org.etsi.ttcn.tci.Value; +import org.etsi.ttcn.tri.TriMessage; + +/** + * + * Note that "Enable Internal Codec" field shall be set to true + * + */ +public class BuiltInCodec implements TciCDProvided { + + /** + * Logger instance + */ + protected final static Logger _logger = Logger.getLogger("org.etsi.its"); + + private String _encodingName; + + /** + * Constructor + */ + public BuiltInCodec(final String encodingName) { + _logger.entering("BuiltInCodec", "BuiltInCodec", encodingName); + + if (encodingName.equals("LibItsDenm_asn1")) { + _encodingName = "DENM_PDU_Descriptions"; + } else if (encodingName.equals("LibItsCam_asn1")) { + _encodingName = "CAM_PDU_Descriptions"; + } else if (encodingName.equals("LibItsCALMmsap_asn1")) { + _encodingName = "CALMmsap"; + } else if (encodingName.equals("LibItsCALMllsap_asn1")) { + _encodingName = "CALMllsap"; + } else if (encodingName.equals("LibItsFntp_asn1")) { + _encodingName = "CALMfntp"; + } else if (encodingName.equals("LibItsFsap_asn1")) { + _encodingName = "CALMfsap"; + } else if (encodingName.equals("LibItsIicp_asn1")) { + _encodingName = "CALMiitsscu"; + } else { + _encodingName = ""; + } + } + + /** + * This operation decodes message according to the encoding rules and returns a TTCN-3 value. + * The decodingHypothesis shall be used to determine whether the encoded value can be decoded. + * If an encoding rule is not self-sufficient, i.e. if the encoded message does not inherently + * contain its type decodingHypothesis shall be used. If the encoded value can be decoded without + * the decoding hypothesis, the distinct null value shall be returned if the type determined from + * the encoded message is not compatible with the decoding hypothesis + * + * @param message The encoded message to be decoded + * @param decodingHypothesis The hypothesis the decoding can be based on + * @return Returns the decoded value, if the value is of a compatible type as the decodingHypothesis, else the distinct value null + * + * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.2.1 decode + */ + @Override + public Value decode(final TriMessage message, final Type decodingHypothesis) { + _logger.entering("BuiltInCodec", "decode", decodingHypothesis.getName()); + + TriMessageEx msg = TriProvider.getInstance().getTriFactory().createMessageEx(); + msg.setEncodedMessage(message.getEncodedMessage()); + if (_logger.isLoggable(Level.ALL)) ByteHelper.dump("BuiltInCodec.decode: ", msg.getEncodedMessage()); + + String type = String.format("%s.%s", _encodingName, decodingHypothesis.getName()); + _logger.info("Type: " + type); + Type asnOriginalType = getTypeForName(type); + // Check which type class the decoding hypothesis is of + Value value = TciProvider.getInstance().getSystemInterface().internalDecode(msg, asnOriginalType); + _logger.exiting("BuiltInCodec", "decode", value.toString()); + return value; + } + + @Override + public TriMessage encode(final Value template) { + _logger.entering("BuiltInCodec", "encode", template.getType().getName()); + + RecordValue asn1Value = (RecordValue)template; + String type = String.format("%s.%s", _encodingName, template.getType().getName()); + _logger.info("Type: " + type); + Type asnOriginalType = getTypeForName(type); + if (asnOriginalType != null) { + RecordValue internalASNEncodecValue = (RecordValue)asnOriginalType.newInstance(); + String[] fields = internalASNEncodecValue.getFieldNames(); + for(String field: fields) { + _logger.info(String.format("Process field %s", field)); + Value fieldValue = asn1Value.getField(field); + if(fieldValue.notPresent()) { + _logger.info(String.format("Field %s was omitted", field)); + internalASNEncodecValue.setFieldOmitted(field); + } else { + _logger.info(String.format("Field %s was added", field)); + internalASNEncodecValue.setField(field, fieldValue); + } + } // End of 'for' statement + _logger.info("Call internal codec"); + TriMessage msg = TciProvider.getInstance().getSystemInterface().internalEncode(internalASNEncodecValue); + ByteHelper.dump("BuiltInCodec.encode: ", msg.getEncodedMessage()); + _logger.exiting("BuiltInCodec", "encode"); + return msg; + } + + _logger.exiting("BuiltInCodec", "encode", "null"); + return null; + } + + private Type getTypeForName(final String type) { + _logger.entering("BuiltInCodec", "getTypeForName", type); + + Type asnOriginalType = TciProvider.getInstance().getTciCDRequired().getTypeForName(type); + if (asnOriginalType == null) { // Failed with default mechanism, try with External Attributes mechanism +// type = decodingHypothesis.getName(); //FIXME External Attributes mechanism does not work + String type_ = ""; + if (type.endsWith("nfSapPrimitivesUp")) { + type_ = String.format("%s.%s", _encodingName, "NFsapPrimitivesUp"); + } else if (type.endsWith("faSapPrimitivesUp")) { + type_ = String.format("%s.%s", _encodingName, "FAsapPrimitivesUp"); + } else if (type.endsWith("mnRequestRequest")) { + type_ = String.format("%s.%s", _encodingName, "MN_Request_request"); + } else if (type.endsWith("mfCommandRequest")) { + type_ = String.format("%s.%s", _encodingName, "MF_Command_request"); + } else if (type.endsWith("miCommandRequest")) { + type_ = String.format("%s.%s", _encodingName, "MI_Command_request"); + } else if (type.endsWith("miCommandConfirm")) { + type_ = String.format("%s.%s", _encodingName, "MI_Command_confirm"); + } else if (type.endsWith("miRequestRequest")) { + type_ = String.format("%s.%s", _encodingName, "MI_Request_request"); + } else if (type.endsWith("miRequestConfirm")) { + type_ = String.format("%s.%s", _encodingName, "MI_Request_confirm"); + } else if (type.endsWith("miSetRequest")) { + type_ = String.format("%s.%s", _encodingName, "MI_Set_request"); + } else if (type.endsWith("miSetConfirm")) { + type_ = String.format("%s.%s", _encodingName, "MI_Set_confirm"); + } else if (type.endsWith("miGetRequest")) { + type_ = String.format("%s.%s", _encodingName, "MI_Get_request"); + } else if (type.endsWith("miGetConfirm")) { + type_ = String.format("%s.%s", _encodingName, "MI_Get_confirm"); + } if (type.endsWith("fntpNPDU")) { + type_ = String.format("%s.%s", _encodingName, "INsapPrimitivesUp"); + } + _logger.info("Type: " + type_); + asnOriginalType = TciProvider.getInstance().getTciCDRequired().getTypeForName(type_); + } + + _logger.exiting("BuiltInCodec", "getTypeForName", asnOriginalType.getName()); + return asnOriginalType; + } // End of method getTypeForName + +} // End of class BuiltInCodec diff --git a/javasrc/tool/org/etsi/its/tool/elvior/GetValueStructure.java b/javasrc/tool/org/etsi/its/tool/elvior/GetValueStructure.java new file mode 100644 index 000000000..ddf964204 --- /dev/null +++ b/javasrc/tool/org/etsi/its/tool/elvior/GetValueStructure.java @@ -0,0 +1,121 @@ +package org.etsi.its.tool.elvior; + +import org.elvior.ttcn.tritci.IntegerValueEx; +import org.etsi.ttcn.tci.BitstringValue; +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.HexstringValue; +import org.etsi.ttcn.tci.OctetstringValue; +import org.etsi.ttcn.tci.RecordOfValue; +import org.etsi.ttcn.tci.RecordValue; +import org.etsi.ttcn.tci.TciTypeClass; +import org.etsi.ttcn.tci.UnionValue; +import org.etsi.ttcn.tci.Value; + +public class GetValueStructure { + + static String indent = null; + static StringBuilder buffer = null; + + static public void displayValueStructure(final Value value) { + buffer = new StringBuilder(); + indent = ""; + LogValueDataStructure(value); +// System.out.println(buffer.toString()); + } + + static public String getValueStructure(final Value value) { + buffer = new StringBuilder(); + indent = ""; + LogValueDataStructure(value); + return buffer.toString(); + } + + static private void LogValueDataStructure(final Value value) { + if (value.notPresent()) { + buffer.append(indent + value.getClass().getName() + " : omitted" + "\n"); + return; + } + switch (value.getType().getTypeClass()) { + case TciTypeClass.BOOLEAN: { + BooleanValue bv = (BooleanValue)value; + buffer.append(indent + bv.getClass().getName() + " : " + new java.lang.Boolean(bv.getBoolean()) + " - encode : " + bv.getValueEncoding() + " - variant : " + bv.getValueEncodingVariant() + "\n"); + } + break; + case TciTypeClass.INTEGER: { + IntegerValueEx iv = (IntegerValueEx)value; + buffer.append(indent + iv.getClass().getName() + " : " + iv.getInt64() + " - encode : " + iv.getValueEncoding() + " - variant : " + iv.getValueEncodingVariant() + "\n"); + } + break; + case TciTypeClass.FLOAT: { + FloatValue fv = (FloatValue)value; + buffer.append(indent + fv.getClass().getName() + " : " + fv.getFloat() + " - encode : " + fv.getValueEncoding() + " - variant : " + fv.getValueEncodingVariant() + "\n"); + } + break; + case TciTypeClass.CHARSTRING: { + CharstringValue csv = (CharstringValue)value; + buffer.append(indent + csv.getClass().getName() + " : " + csv.getString() + " - encode : " + csv.getValueEncoding() + " - variant : " + csv.getValueEncodingVariant() + "\n"); + } + break; + case TciTypeClass.BITSTRING: { + BitstringValue bv = (BitstringValue)value; + buffer.append(indent + bv.getClass().getName() + " : " + bv.getString() + " - encode : " + bv.getValueEncoding() + " - variant : " + bv.getValueEncodingVariant() + "\n"); + } + break; + case TciTypeClass.OCTETSTRING: { + OctetstringValue ov = (OctetstringValue)value; + buffer.append(indent + ov.getClass().getName() + " : " + ov.getString() + " - encode : " + ov.getValueEncoding() + " - variant : " + ov.getValueEncodingVariant() + "\n"); + } + break; + case TciTypeClass.HEXSTRING: { + HexstringValue hv = (HexstringValue)value; + buffer.append(indent + hv.getClass().getName() + " : " + hv.getString() + " - encode : " + hv.getValueEncoding() + " - variant : " + hv.getValueEncodingVariant() + "\n"); + } + break; + case TciTypeClass.ENUMERATED: { + EnumeratedValue ev = (EnumeratedValue)value; + buffer.append(indent + ev.getClass().getName() + " : " + ev.getEnum() + " - encode : " + ev.getValueEncoding() + " - variant : " + ev.getValueEncodingVariant() + "\n"); + } + break; + case TciTypeClass.SET: + // No break; + case TciTypeClass.RECORD: { + RecordValue rv = (RecordValue)value; + buffer.append(indent + rv.getClass().getName() + " - encode : " + rv.getValueEncoding() + " - variant : " + rv.getValueEncodingVariant() + "\n"); + indent += "\t"; + for (String key : rv.getFieldNames()) { + LogValueDataStructure(rv.getField(key)); + } // End of 'for'statement + indent = indent.substring(0, indent.length() -1); + } + break; + case TciTypeClass.ANYTYPE: + // No break; + case TciTypeClass.UNION: { + UnionValue uv = (UnionValue)value; + buffer.append(indent + uv.getClass().getName() + " - encode : " + uv.getValueEncoding() + " - variant : " + uv.getValueEncodingVariant() + "\n"); + indent += "\t"; + LogValueDataStructure(uv.getVariant(uv.getPresentVariantName())); + indent = indent.substring(0, indent.length() -1); + } + break; + case TciTypeClass.RECORD_OF: + // No break; + case TciTypeClass.SET_OF: { + RecordOfValue rofv = (RecordOfValue)value; + buffer.append(indent + rofv.getClass().getName() + " - encode : " + rofv.getValueEncoding() + " : " + rofv.getLength() + " - variant : " + rofv.getValueEncodingVariant() + "\n"); + indent += "\t"; + for (int key = 0; key < rofv.getLength(); key++) { + LogValueDataStructure(rofv.getField(key)); + } // End of 'for'statement + indent = indent.substring(0, indent.length() -1); + } + break; + default: + throw new RuntimeException("Unimplemented class type: " + value.getType().getTypeClass()); + } // End of 'switch' value + } + +} diff --git a/javasrc/tool/org/etsi/its/tool/elvior/Its_CodecProvider.java b/javasrc/tool/org/etsi/its/tool/elvior/Its_CodecProvider.java index 4746f11cb..0c9cb1c27 100644 --- a/javasrc/tool/org/etsi/its/tool/elvior/Its_CodecProvider.java +++ b/javasrc/tool/org/etsi/its/tool/elvior/Its_CodecProvider.java @@ -10,11 +10,11 @@ import org.elvior.ttcn.tritci.ChannelEventHandler; import org.elvior.ttcn.tritci.TciProvider; import org.elvior.ttcn.tritci.TriTciChannel; import org.etsi.codec.ITCIRequired; +import org.etsi.codec.ITciCDWrapper; import org.etsi.codec.TciCDWrapperFactory; import org.etsi.tool.elvior.TciCDWrapper; import org.etsi.ttcn.codec.CodecFactory; import org.etsi.ttcn.tci.TciCDProvided; -import org.etsi.ttcn.tci.TciCDRequired; import org.etsi.ttcn.tci.Type; import org.etsi.ttcn.tci.Value; import org.etsi.ttcn.tri.TriMessage; @@ -28,12 +28,16 @@ public class Its_CodecProvider implements TciCDProvided, ChannelEventHandler, IT */ private final static Logger _logger = Logger.getLogger("org.etsi.its"); - private TciCDRequired _cdReq; + private ITciCDWrapper _cdReq; + + private CodecFactory _cf; public Its_CodecProvider() { _logger.entering("Its_CodecProvider", "Its_CodecProvider"); // Load Codec settings + _cdReq = null; + _cf = null; try { _properties.load(MainCodec.class.getResourceAsStream("/org/etsi/its/tool/elvior/res/codec.properties")); } catch (IOException e) { @@ -62,7 +66,26 @@ public class Its_CodecProvider implements TciCDProvided, ChannelEventHandler, IT // Register this object as the receiver of events generated by TestCast framework channel.setEventHandler(this); + initializeCodecs(); + } + + private void initializeCodecs() { TciCDWrapperFactory.getInstance().setImpl(new TciCDWrapper()); + _cdReq = TciCDWrapperFactory.getTciCDInstance(); + + // Register External codecs + _cf = CodecFactory.getInstance(); + // TODO Reuse Build-in codec here + + String[] asn1Codecs = _properties.getProperty("ASN.1Codecs", "").split(","); + for (String codec : asn1Codecs) { + String[] paths = _properties.getProperty(codec, "").split(","); + try { + _cf.setExternalCodec(paths[0], (TciCDProvided) Class.forName(paths[1]).newInstance()); + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { + e.printStackTrace(); + } + } // End of 'foreach' loop } public void run() { @@ -118,13 +141,13 @@ public class Its_CodecProvider implements TciCDProvided, ChannelEventHandler, IT return null; } Value value = codec.decode(message, decodingHypothesis); - _logger.exiting("decode", (value != null) ? value.toString() : "(null)"); + _logger.exiting("Its_CodecProvider.decode", (value != null) ? GetValueStructure.getValueStructure(value) : "(null)"); return value; } @Override public TriMessage encode(Value value) { - _logger.entering( + /*_logger.entering( "encode", String.format( ">>> encode: %s - %s - %s - %s - %s - %s - %s - %s - %s", @@ -138,8 +161,8 @@ public class Its_CodecProvider implements TciCDProvided, ChannelEventHandler, IT value.getValueEncodingVariant(), (value.notPresent() == true) ? "true" : "false" ) - ); - + );*/ +// System.out.println(">>> encode: " + value.getType().getName()); String encodingName = value.getType().getTypeEncoding(); if ((encodingName != null) && !encodingName.startsWith("Lib")) { encodingName = value.getType().getDefiningModule().getModuleName(); @@ -150,6 +173,7 @@ public class Its_CodecProvider implements TciCDProvided, ChannelEventHandler, IT if (codec == null) { return null; } + _logger.info("Value to encode: " + GetValueStructure.getValueStructure(value)); TriMessage res = codec.encode(value); _logger.exiting("encode", res.toString()); return res; @@ -163,34 +187,8 @@ public class Its_CodecProvider implements TciCDProvided, ChannelEventHandler, IT * @return The codec associated to the specified encoding identifier */ @Override - public TciCDProvided getCodec(String encodingName) { - _logger.entering("getCodec", encodingName); - - _cdReq = TciProvider.getInstance().getTciCDRequired(); - - // Register External codecs - CodecFactory cf = CodecFactory.getInstance(); - // TODO Reuse Build-in codec here - - String[] asn1Codecs = _properties.getProperty("ASN.1Codecs", "").split(","); - System.out.println("getCodec: " + asn1Codecs); - for (String codec : asn1Codecs) { - System.out.println("getCodec: " + codec); - String[] paths = _properties.getProperty(codec, "").split(","); - try { - cf.setExternalCodec(paths[0], (TciCDProvided) Class.forName(paths[1]).newInstance()); - } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { - e.printStackTrace(); - } - } // End of 'foreach' loop -// TODO To be removed -// cf.setExternalCodec("LibItsFntp_asn1", cs.getCodec("LibItsFntp_asn1")); -// cf.setExternalCodec("LibItsFsap_asn1", cs.getCodec("LibItsFsap_asn1")); -// cf.setExternalCodec("LibItsIicp_asn1", cs.getCodec("LibItsIicp_asn1")); -// cf.setExternalCodec("LibItsCALMmsap_asn1", cs.getCodec("LibItsCALMmsap_asn1")); -// cf.setExternalCodec("LibItsCALMllsap_asn1", cs.getCodec("LibItsCALMllsap_asn1")); - //TODO: add V2G external codecs (xsd) - + public TciCDProvided getCodec(final String encodingName) { + // FIXME Remove argument here and in the interface ITCIRequired return new Codec(); } diff --git a/javasrc/tool/org/etsi/its/tool/elvior/LibItsCALMllsap_asn1.java b/javasrc/tool/org/etsi/its/tool/elvior/LibItsCALMllsap_asn1.java new file mode 100644 index 000000000..707e0da5e --- /dev/null +++ b/javasrc/tool/org/etsi/its/tool/elvior/LibItsCALMllsap_asn1.java @@ -0,0 +1,31 @@ +package org.etsi.its.tool.elvior; + +import org.etsi.ttcn.tci.Type; + +public class LibItsCALMllsap_asn1 extends LibIts_asn1 { + + /** + * Constructor + */ + public LibItsCALMllsap_asn1() { + _logger.entering("LibItsCALMllsap_asn1", "LibItsCALMllsap_asn1"); + _encodingName = "CALMllsap"; + } + + protected Type getTypeForName(final String type) { + _logger.entering("LibItsCALMllsap_asn1", "getTypeForName", type); + + String type_ = type; + if (type.endsWith("mnRequestRequest")) { + type_ = String.format("%s.%s", _encodingName, "MN_Request_request"); + } else if (type.endsWith("msgIn_in")) { + type_ = String.format("%s.%s", _encodingName, "INsapPrimitivesDown"); + } + + Type asnOriginalType = super.getTypeForName(type_); + + _logger.exiting("LibItsCALMllsap_asn1", "getTypeForName", asnOriginalType.getName()); + return asnOriginalType; + } // End of method getTypeForName + +} // End of class LibItsCALMllsap_asn1 diff --git a/javasrc/tool/org/etsi/its/tool/elvior/LibItsCALMmsap_asn1.java b/javasrc/tool/org/etsi/its/tool/elvior/LibItsCALMmsap_asn1.java new file mode 100644 index 000000000..cc3e1265e --- /dev/null +++ b/javasrc/tool/org/etsi/its/tool/elvior/LibItsCALMmsap_asn1.java @@ -0,0 +1,41 @@ +package org.etsi.its.tool.elvior; + +import org.etsi.ttcn.tci.Type; + +public class LibItsCALMmsap_asn1 extends LibIts_asn1 { + + /** + * Constructor + */ + public LibItsCALMmsap_asn1() { + _logger.entering("LibItsCALMmsap_asn1", "LibItsCALMmsap_asn1"); + _encodingName = "CALMmsap"; + } + + protected Type getTypeForName(final String type) { + _logger.entering("LibItsCALMmsap_asn1", "getTypeForName", type); + + String type_ = type; + if (type.endsWith("mfRequestRequest")) { + type_ = String.format("%s.%s", _encodingName, "MF_Request_request"); + } else if (type.endsWith("mnRequestRequest")) { + type_ = String.format("%s.%s", _encodingName, "MN_Request_request"); + } else if (type.endsWith("miRequestRequest")) { + type_ = String.format("%s.%s", _encodingName, "MI_Request_request"); + } else if (type.endsWith("mf_Command_request")) { + type_ = String.format("%s.%s", _encodingName, "MF_Command_request"); + } else if (type.endsWith("mn_Command_request")) { + type_ = String.format("%s.%s", _encodingName, "MN_Command_request"); + } else if (type.endsWith("mi_Command_request")) { + type_ = String.format("%s.%s", _encodingName, "MI_Command_request"); + } else if (type.endsWith("faSapPrimitivesUp")) { + type_ = String.format("%s.%s", _encodingName, "FAsapPrimitivesUp"); + } + + Type asnOriginalType = super.getTypeForName(type_); + + _logger.exiting("LibItsCALMmsap_asn1", "getTypeForName", asnOriginalType.getName()); + return asnOriginalType; + } // End of method getTypeForName + +} // End of class LibItsCALMmsap_asn1 diff --git a/javasrc/tool/org/etsi/its/tool/elvior/LibItsCam_asn1.java b/javasrc/tool/org/etsi/its/tool/elvior/LibItsCam_asn1.java index 2000fa157..f1d46ad23 100644 --- a/javasrc/tool/org/etsi/its/tool/elvior/LibItsCam_asn1.java +++ b/javasrc/tool/org/etsi/its/tool/elvior/LibItsCam_asn1.java @@ -1,5 +1,9 @@ package org.etsi.its.tool.elvior; +import org.etsi.ttcn.tci.Type; +import org.etsi.ttcn.tci.Value; +import org.etsi.ttcn.tri.TriMessage; + /** * @@ -8,7 +12,6 @@ package org.etsi.its.tool.elvior; */ public class LibItsCam_asn1 extends LibIts_asn1 { - /** * Constructor */ @@ -17,4 +20,16 @@ public class LibItsCam_asn1 extends LibIts_asn1 { _encodingName = "CAM_PDU_Descriptions"; } -} // End of class BuiltInCodec + @Override + public Value decode(final TriMessage message, final Type decodingHypothesis) { + _logger.entering("LibItsCam_asn1", "decode", decodingHypothesis.getName()); + + if (decodingHypothesis.getName().endsWith("camPacket")) { + Type type = getTypeForName("CAM_PDU_Descriptions.CAM"); + return super.decode(message, type); + } + + return super.decode(message, decodingHypothesis); + } + +} // End of class LibItsCam_asn1 diff --git a/javasrc/tool/org/etsi/its/tool/elvior/LibItsDenm_asn1.java b/javasrc/tool/org/etsi/its/tool/elvior/LibItsDenm_asn1.java index 861bf1aa9..08ec479c6 100644 --- a/javasrc/tool/org/etsi/its/tool/elvior/LibItsDenm_asn1.java +++ b/javasrc/tool/org/etsi/its/tool/elvior/LibItsDenm_asn1.java @@ -1,5 +1,9 @@ package org.etsi.its.tool.elvior; +import org.etsi.ttcn.tci.Type; +import org.etsi.ttcn.tci.Value; +import org.etsi.ttcn.tri.TriMessage; + /** * * Note that "Enable Internal Codec" field shall be set to true @@ -15,4 +19,16 @@ public class LibItsDenm_asn1 extends LibIts_asn1 { _encodingName = "DENM_PDU_Descriptions"; } + @Override + public Value decode(final TriMessage message, final Type decodingHypothesis) { + _logger.entering("LibItsDenm_asn1", "decode", decodingHypothesis.getName()); + + if (decodingHypothesis.getName().endsWith("denmPacket")) { + Type type = getTypeForName("DENM_PDU_Descriptions.DENM"); + return super.decode(message, type); + } + + return super.decode(message, decodingHypothesis); + } + } // End of class BuiltInCodec diff --git a/javasrc/tool/org/etsi/its/tool/elvior/LibItsFntp_asn1.java b/javasrc/tool/org/etsi/its/tool/elvior/LibItsFntp_asn1.java new file mode 100644 index 000000000..5810e8e45 --- /dev/null +++ b/javasrc/tool/org/etsi/its/tool/elvior/LibItsFntp_asn1.java @@ -0,0 +1,33 @@ +package org.etsi.its.tool.elvior; + +import org.etsi.ttcn.tci.Type; + +public class LibItsFntp_asn1 extends LibIts_asn1 { + + /** + * Constructor + */ + public LibItsFntp_asn1() { + _logger.entering("LibItsFntp_asn1", "LibItsFntp_asn1"); + _encodingName = "CALMfntp"; + } + + protected Type getTypeForName(final String type) { + _logger.entering("LibItsFntp_asn1", "getTypeForName", type); + + String type_ = type; + if (type.endsWith("nfSapPrimitivesUp")) { + type_ = String.format("%s.%s", _encodingName, "NFsapPrimitivesUp"); + } else if (type.endsWith("mnRequestRequest")) { + type_ = String.format("%s.%s", _encodingName, "MN_Request_request"); + } else if (type.endsWith("msgIn_nf")) { + type_ = String.format("%s.%s", _encodingName, "NFsapPrimitivesDown"); + } + + Type asnOriginalType = super.getTypeForName(type_); + + _logger.exiting("LibItsFntp_asn1", "getTypeForName", asnOriginalType.getName()); + return asnOriginalType; + } // End of method getTypeForName + +} // End of class LibItsFntp_asn1 diff --git a/javasrc/tool/org/etsi/its/tool/elvior/LibItsFsap_asn1.java b/javasrc/tool/org/etsi/its/tool/elvior/LibItsFsap_asn1.java new file mode 100644 index 000000000..f7307f6d7 --- /dev/null +++ b/javasrc/tool/org/etsi/its/tool/elvior/LibItsFsap_asn1.java @@ -0,0 +1,13 @@ +package org.etsi.its.tool.elvior; + +public class LibItsFsap_asn1 extends LibIts_asn1 { + + /** + * Constructor + */ + public LibItsFsap_asn1() { + _logger.entering("LibItsFsap_asn1", "LibItsFsap_asn1"); + _encodingName = "CALMfsap"; + } + +} // End of class LibItsFsap_asn1 diff --git a/javasrc/tool/org/etsi/its/tool/elvior/LibItsIicp_asn1.java b/javasrc/tool/org/etsi/its/tool/elvior/LibItsIicp_asn1.java new file mode 100644 index 000000000..7b0744bcc --- /dev/null +++ b/javasrc/tool/org/etsi/its/tool/elvior/LibItsIicp_asn1.java @@ -0,0 +1,33 @@ +package org.etsi.its.tool.elvior; + +import org.etsi.ttcn.tci.Type; + +public class LibItsIicp_asn1 extends LibIts_asn1 { + + /** + * Constructor + */ + public LibItsIicp_asn1() { + _logger.entering("LibItsIicp_asn1", "LibItsIicp_asn1"); + _encodingName = "CALMiitsscu"; + } + + protected Type getTypeForName(final String type) { + _logger.entering("LibItsIicp_asn1", "getTypeForName", type); + + String type_ = type; + if (type.endsWith("msg_req")) { + type_ = String.format("%s.%s", _encodingName, "IIC_Request"); + } else if (type.endsWith("msg_resp")) { + type_ = String.format("%s.%s", _encodingName, "IIC_Response"); + } else if (type.endsWith("mcmdRq")) { + type_ = String.format("%s.%s", _encodingName, "McmdRq"); + } + + Type asnOriginalType = super.getTypeForName(type_); + + _logger.exiting("LibItsIicp_asn1", "getTypeForName", asnOriginalType.getName()); + return asnOriginalType; + } // End of method getTypeForName + +} // End of class LibItsIicp_asn1 diff --git a/javasrc/tool/org/etsi/its/tool/elvior/LibIts_asn1.java b/javasrc/tool/org/etsi/its/tool/elvior/LibIts_asn1.java index 652a43e08..d9938510b 100644 --- a/javasrc/tool/org/etsi/its/tool/elvior/LibIts_asn1.java +++ b/javasrc/tool/org/etsi/its/tool/elvior/LibIts_asn1.java @@ -3,12 +3,14 @@ package org.etsi.its.tool.elvior; import java.util.logging.Level; import java.util.logging.Logger; +import org.elvior.ttcn.tritci.IntegerValueEx; import org.elvior.ttcn.tritci.TciProvider; import org.elvior.ttcn.tritci.TriMessageEx; import org.elvior.ttcn.tritci.TriProvider; import org.etsi.common.ByteHelper; import org.etsi.ttcn.tci.RecordValue; import org.etsi.ttcn.tci.TciCDProvided; +import org.etsi.ttcn.tci.TciTypeClass; import org.etsi.ttcn.tci.Type; import org.etsi.ttcn.tci.Value; import org.etsi.ttcn.tri.TriMessage; @@ -62,7 +64,7 @@ public class LibIts_asn1 implements TciCDProvided { Type asnOriginalType = getTypeForName(type); // Check which type class the decoding hypothesis is of _logger.info("asnOriginalType: " + asnOriginalType.getName()); - Value value = TciProvider.getInstance().getSystemInterface().InternalDecode(msg, asnOriginalType); + Value value = TciProvider.getInstance().getSystemInterface().internalDecode(msg, asnOriginalType); _logger.exiting("LibIts_asn1", "decode", value.toString()); return value; } @@ -71,26 +73,37 @@ public class LibIts_asn1 implements TciCDProvided { public TriMessage encode(final Value template) { _logger.entering("LibIts_asn1", "encode", template.getType().getName()); - RecordValue asn1Value = (RecordValue)template; String type = String.format("%s.%s", _encodingName, template.getType().getName()); _logger.info("Type: " + type); Type asnOriginalType = getTypeForName(type); if (asnOriginalType != null) { - RecordValue internalASNEncodecValue = (RecordValue)asnOriginalType.newInstance(); - String[] fields = internalASNEncodecValue.getFieldNames(); + Value internalASNEncodecValue = null; + switch (template.getType().getTypeClass()) { + case TciTypeClass.RECORD: + internalASNEncodecValue = (RecordValue)asnOriginalType.newInstance(); + String[] fields = ((RecordValue)internalASNEncodecValue).getFieldNames(); + RecordValue asn1Value = (RecordValue)template; for(String field: fields) { _logger.info(String.format("Process field %s", field)); Value fieldValue = asn1Value.getField(field); if(fieldValue.notPresent()) { _logger.info(String.format("Field %s was omitted", field)); - internalASNEncodecValue.setFieldOmitted(field); + ((RecordValue)internalASNEncodecValue).setFieldOmitted(field); } else { _logger.info(String.format("Field %s was added", field)); - internalASNEncodecValue.setField(field, fieldValue); + ((RecordValue)internalASNEncodecValue).setField(field, fieldValue); } } // End of 'for' statement + break; + case TciTypeClass.INTEGER: + internalASNEncodecValue = (IntegerValueEx)asnOriginalType.newInstance(); + ((IntegerValueEx)internalASNEncodecValue).setInt64(((IntegerValueEx)template).getInt64()); + break; + default: + throw new RuntimeException("Unimplemented type " + template.getType().getTypeClass()); + } // End of 'switch' statement _logger.info("Call internal codec"); - TriMessage msg = TciProvider.getInstance().getSystemInterface().InternalEncode(internalASNEncodecValue); + TriMessage msg = TciProvider.getInstance().getSystemInterface().internalEncode(internalASNEncodecValue); ByteHelper.dump("LibIts_asn1.encode: ", msg.getEncodedMessage()); _logger.exiting("LibIts_asn1", "encode"); return msg; diff --git a/javasrc/tool/org/etsi/its/tool/elvior/PluginAdapter.java b/javasrc/tool/org/etsi/its/tool/elvior/PluginAdapter.java index b4e4ae4ce..49dbcafd8 100644 --- a/javasrc/tool/org/etsi/its/tool/elvior/PluginAdapter.java +++ b/javasrc/tool/org/etsi/its/tool/elvior/PluginAdapter.java @@ -4,13 +4,19 @@ */ package org.etsi.its.tool.elvior; +import java.io.IOException; +import java.math.BigInteger; +import java.util.Properties; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; import java.util.logging.Logger; +import org.elvior.ttcn.tritci.ChannelEventHandler; +import org.elvior.ttcn.tritci.IntegerValueEx; import org.elvior.ttcn.tritci.TciProvider; import org.elvior.ttcn.tritci.TriFactory; import org.elvior.ttcn.tritci.TriProvider; import org.elvior.ttcn.tritci.TriTciChannel; -import org.elvior.ttcn.tritci.ChannelEventHandler; import org.etsi.adapter.TERFactory; import org.etsi.codec.ITciCDWrapper; import org.etsi.codec.TciCDWrapperFactory; @@ -19,13 +25,38 @@ import org.etsi.its.extfunc.IItsExternalFunctionsProvider; import org.etsi.its.extfunc.ItsExternalFunctionsProvider; import org.etsi.tool.elvior.TciCDWrapper; import org.etsi.tool.elvior.TeRequiredImpl; +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 org.etsi.ttcn.tci.TciParameterList; import org.etsi.ttcn.tci.TciValueList; import org.etsi.ttcn.tci.Value; -import org.etsi.ttcn.tri.*; +import org.etsi.ttcn.tri.TriAddress; +import org.etsi.ttcn.tri.TriAddressList; +import org.etsi.ttcn.tri.TriBoolean; +import org.etsi.ttcn.tri.TriCommunicationSA; +import org.etsi.ttcn.tri.TriCommunicationTE; +import org.etsi.ttcn.tri.TriComponentId; +import org.etsi.ttcn.tri.TriException; +import org.etsi.ttcn.tri.TriFunctionId; +import org.etsi.ttcn.tri.TriLong; +import org.etsi.ttcn.tri.TriMessage; +import org.etsi.ttcn.tri.TriParameter; +import org.etsi.ttcn.tri.TriParameterList; +import org.etsi.ttcn.tri.TriParameterPassingMode; +import org.etsi.ttcn.tri.TriPlatformPA; +import org.etsi.ttcn.tri.TriPortId; +import org.etsi.ttcn.tri.TriPortIdList; +import org.etsi.ttcn.tri.TriSignatureId; +import org.etsi.ttcn.tri.TriStatus; +import org.etsi.ttcn.tri.TriTestCaseId; +import org.etsi.ttcn.tri.TriTimerDuration; +import org.etsi.ttcn.tri.TriTimerId; import org.etsi.ttcn.xtri.xTriCommunicationSA; public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xTriCommunicationSA, TriPlatformPA, ChannelEventHandler { @@ -34,6 +65,8 @@ public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xT */ private org.etsi.its.adapter.TestAdapter _itsTestAdapter; + private static Properties _properties = new Properties(); + /** * Logger instance */ @@ -48,6 +81,27 @@ public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xT public PluginAdapter() { _logger.entering("PluginAdapter", "Constructor"); + // Load TA settings + try { + _properties.load(MainTA.class.getResourceAsStream("/org/etsi/its/tool/elvior/res/ta.properties")); + } catch (IOException e) { + e.printStackTrace(); + } + String debugLevel = _properties.getProperty("DEBUG_ENABLED", "OFF"); + Level level = Level.OFF; + if (debugLevel.equalsIgnoreCase("ALL")) { + level = Level.ALL; + } else if (debugLevel.equalsIgnoreCase("INFO")) { + level = Level.INFO; + } else if (debugLevel.equalsIgnoreCase("SEVERE")) { + level = Level.SEVERE; + } else if (!debugLevel.equalsIgnoreCase("OFF")) { + System.err.println("Unsupported logging level: " + debugLevel); + } + _logger.addHandler(new ConsoleHandler()); + _logger.setLevel(level); + _logger.getHandlers()[0].setLevel(level); + // Register this object as the instance implementing the TRI-SA interface TriProvider.getInstance().setTriCommunicationSA(this); // Register this object as the instance implementing the TRI-PA interface @@ -192,7 +246,7 @@ public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xT } public TriStatus triExternalFunction(TriFunctionId functionId, TriParameterList parameterList, TriParameter returnValue) { - _logger.entering("PluginAdapter", "triExternalFunction", functionId.getFunctionName() + " - " + parameterList + " - " + returnValue.getParameterName() + " - " + returnValue.getParameterPassingMode()); + _logger.entering("PluginAdapter", "triExternalFunction", functionId.getFunctionName()); // + " - " + parameterList + " - " + returnValue.getParameterName() + " - " + returnValue.getParameterPassingMode()); TriStatus result = m_triOK; if ( @@ -219,13 +273,46 @@ public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xT } else if (functionId.getFunctionName().endsWith("fx_getCurrentTime")) { // Gets the current time exec_getCurrentTime(returnValue); + } else if (functionId.getFunctionName().endsWith("xf_parseIpv6Address")) { + exec_parseIpv6Address(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_hashWithSha256") && (parameterList.size() == 1)) { + exec_hashWithSha256(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_signWithEcdsaNistp256WithSha256") && (parameterList.size() == 2)) { + exec_signWithEcdsaNistp256WithSha256(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_verifyWithEcdsaNistp256WithSha256") && (parameterList.size() == 4)) { + exec_verifyWithEcdsaNistp256WithSha256(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_generateKeyPair") && (parameterList.size() == 3)) { + exec_generateKeyPair(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_dms2dd") && (parameterList.size() == 4)) { + exec_dms2dd(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_isValidPolygonalRegion") && (parameterList.size() == 1)) { + exec_isValidPolygonalRegion(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_isPolygonalRegionInside") && (parameterList.size() == 2)) { + exec_isPolygonalRegionInside(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_isLocationInsideCircularRegion") && (parameterList.size() == 2)) { + exec_isLocationInsideCircularRegion(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_isLocationInsideRectangularRegion") && (parameterList.size() == 2)) { + exec_isLocationInsideRectangularRegion(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_isLocationInsidePolygonalRegion") && (parameterList.size() == 2)) { + exec_isLocationInsidePolygonalRegion(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_isLocationInsideIdentifiedRegion") && (parameterList.size() == 2)) { + exec_isLocationInsideIdentifiedRegion(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_loadCertificates") && (parameterList.size() == 2)) { + exec_loadCertificates(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_unloadCertificates") && (parameterList.size() == 0)) { + exec_unloadCertificates(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_readCertificate") && (parameterList.size() == 2)) { + exec_readCertificate(parameterList, returnValue); + } else if (functionId.getFunctionName().endsWith("fx_readPrivateKeys") && (parameterList.size() == 3)) { + exec_readPrivateKeys(parameterList, returnValue); } else { + _logger.severe("Unprocessed external function"); result = m_triKO; } - _logger.exiting("PluginAdapter", "triExternalFunction", String.format("%d", result.getStatus())); + _logger.exiting("PluginAdapter", "triExternalFunction", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); return result; } - + public void onConnectionClosed() { _logger.entering("PluginAdapter", "onConnectionClosed"); synchronized(this) { @@ -359,7 +446,7 @@ public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xT @Override public TriStatus xtriSend(TriComponentId compPortId, TriPortId tsiPortId, Value arg2, Value arg3) { - throw new RuntimeException(); + throw new RuntimeException(); } @Override @@ -379,7 +466,7 @@ public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xT @Override public TriStatus triStaticMap(TriPortId arg0, TriPortId arg1) { - throw new RuntimeException(); + throw new RuntimeException(); } private void exec_computeIPv6CheckSum(TriParameterList parameterList, TriParameter returnValue) { @@ -387,8 +474,7 @@ public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xT // Source address (128 bits) byte[] value = parameterList.get(0).getEncodedParameter(); - ITciCDWrapper wrapper = TciCDWrapperFactory.getTciCDInstance(); - OctetstringValue sourceAddress = (OctetstringValue)wrapper.getOctetstring(); + OctetstringValue sourceAddress = (OctetstringValue)TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance(); sourceAddress.setLength(value.length); for (int i = 0; i < value.length; i++) { sourceAddress.setOctet(i, value[i]); @@ -436,33 +522,34 @@ public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xT returnValue.setNumberOfBits(value.length * Byte.SIZE); returnValue.setEncodedParameter(value); - _logger.exiting("PluginAdapter", "exec_computeIPv6CheckSum", String.format("Return value: %d", returnValue.getNumberOfBits())); + _logger.exiting("PluginAdapter", "exec_computeIPv6CheckSum", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); } // End of method exec_computeIPv6CheckSum private void exec_computeDistance(TriParameterList parameterList, TriParameter returnValue) { _logger.entering("PluginAdapter", "exec_computeDistance"); - _logger.info(String.format("Setting parameter %s", parameterList.get(0).getParameterName())); +// _logger.info(String.format("Setting parameter %s: %s", parameterList.get(0).getParameterName(), ByteHelper.byteArrayToString(parameterList.get(0).getEncodedParameter()))); byte[] value = parameterList.get(0).getEncodedParameter(); IntegerValue latitudeA = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance(); latitudeA.setInteger(ByteHelper.byteArrayToInt(value)); - _logger.info(String.format("Setting parameter %s", parameterList.get(1).getParameterName())); +// _logger.info(String.format("Setting parameter %s: %s", parameterList.get(1).getParameterName(), ByteHelper.byteArrayToString(parameterList.get(1).getEncodedParameter()))); value = parameterList.get(1).getEncodedParameter(); IntegerValue longitudeA = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance(); longitudeA.setInteger(ByteHelper.byteArrayToInt(value)); - _logger.info(String.format("Setting parameter %s", parameterList.get(2).getParameterName())); +// _logger.info(String.format("Setting parameter %s: %s", parameterList.get(2).getParameterName(), ByteHelper.byteArrayToString(parameterList.get(2).getEncodedParameter()))); value = parameterList.get(2).getEncodedParameter(); IntegerValue latitudeB = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance(); latitudeB.setInteger(ByteHelper.byteArrayToInt(value)); - _logger.info(String.format("Setting parameter %s", parameterList.get(3).getParameterName())); +// _logger.info(String.format("Setting parameter %s: %s", parameterList.get(3).getParameterName(), ByteHelper.byteArrayToString(parameterList.get(3).getEncodedParameter()))); value = parameterList.get(3).getEncodedParameter(); IntegerValue longitudeB = (IntegerValue)TciProvider.getInstance().getTciCDRequired().getInteger().newInstance(); longitudeB.setInteger(ByteHelper.byteArrayToInt(value)); // Execute the function + _logger.info(String.format("_extfuncsImpl.fx_computeDistance %d, %d, %d, %d", latitudeA.getInteger(), longitudeA.getInteger(), latitudeB.getInteger(), longitudeB.getInteger())); FloatValue distance = _extfuncsImpl.fx_computeDistance( latitudeA, longitudeA, @@ -471,11 +558,11 @@ public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xT ); _logger.info(String.format("fx_computeDistance returns %f", distance.getFloat())); returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); - returnValue.setNumberOfBits(Float.SIZE); - int convert = Float.floatToIntBits(distance.getFloat()); - returnValue.setEncodedParameter(ByteHelper.intToByteArray(convert, Integer.SIZE / Byte.SIZE)); + byte[] convert = ByteHelper.floatToByteArray(distance.getFloat()); + returnValue.setNumberOfBits(convert.length * Byte.SIZE); + returnValue.setEncodedParameter(convert); - _logger.exiting("PluginAdapter", "exec_computeDistance", String.format("Return value: %d", returnValue.getNumberOfBits())); + _logger.exiting("PluginAdapter", "exec_computeDistance", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); } // End of method exec_computeDistance private void exec_computePositionUsingDistance(TriParameterList parameterList, TriParameter returnValue) { @@ -523,12 +610,16 @@ public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xT // Execute the function IntegerValue timestamp = _extfuncsImpl.fx_computeGnTimestamp(); - _logger.info(String.format("exec_computeGnTimestamp returns %d", timestamp.getInteger())); +// _logger.info(String.format("exec_computeGnTimestamp returns %d", timestamp.getInteger())); returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); returnValue.setNumberOfBits(Integer.SIZE); - returnValue.setEncodedParameter(ByteHelper.intToByteArray(timestamp.getInteger(), Integer.SIZE / Byte.SIZE)); + returnValue.setEncodedParameter( + ByteHelper.intToByteArray( + timestamp.getInteger(), + Integer.SIZE / Byte.SIZE + )); - _logger.exiting("PluginAdapter", "exec_computeGnTimestamp", String.format("Return value: %d", returnValue.getNumberOfBits())); + _logger.exiting("PluginAdapter", "exec_computeGnTimestamp", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); } // End of method exec_computeGnTimestamp private void exec_getCurrentTime(TriParameter returnValue) { @@ -536,14 +627,624 @@ public class PluginAdapter implements TriCommunicationSA, TriCommunicationTE, xT // Execute the function IntegerValue time = _extfuncsImpl.fx_getCurrentTime(); - // FIXME To be removed and integer size lenght bug fixed - if (time.getInteger() < 0) time.setInteger(-1 * time.getInteger()); - _logger.info(String.format("exec_getCurrentTime returns %d", time.getInteger())); +// _logger.info(String.format("exec_getCurrentTime returns %d", ((IntegerValueEx)time).getInt64())); returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); - returnValue.setNumberOfBits(Integer.SIZE); - returnValue.setEncodedParameter(ByteHelper.intToByteArray(time.getInteger(), Integer.SIZE / Byte.SIZE)); + returnValue.setNumberOfBits(Long.SIZE); + returnValue.setEncodedParameter( + ByteHelper.longToByteArray( + ((IntegerValueEx)time).getInt64() << 6, // Decoding starts from bit 0, byte 0, so we have to shift the value 6 bits to the left + 6/*Long.SIZE / Byte.SIZE*/ // Encoding on 48 bits + )); - _logger.exiting("PluginAdapter", "exec_getCurrentTime", String.format("Return value: %d", returnValue.getNumberOfBits())); + _logger.exiting("PluginAdapter", "exec_getCurrentTime", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); } // End of method exec_getCurrentTime + + private void exec_generateKeyPair(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_generateKeyPair"); + + // Execute the function + OctetstringValue privateKey = (OctetstringValue) TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance(); + OctetstringValue publicKeyX = (OctetstringValue) TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance(); + OctetstringValue publicKeyY = (OctetstringValue) TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance(); + BooleanValue result = _extfuncsImpl.fx_generateKeyPair(privateKey, publicKeyX, publicKeyY); + _logger.info(String.format("exec_generateKeyPair returns %s", (new Boolean(result.getBoolean())))); + // privateKey + TriParameter Key = parameterList.get(0); + Key.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + byte[] ref = new byte[privateKey.getLength()]; + for (int i = 0; i < ref.length; i++) { + ref[i] = (byte) privateKey.getOctet(i); + } // End 'for' statement + Key.setEncodedParameter(ref); + // publicKeyX + Key = parameterList.get(1); + Key.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + Key.setNumberOfBits(publicKeyX.getLength() * Byte.SIZE); + ref = new byte[publicKeyX.getLength()]; + for (int i = 0; i < ref.length; i++) { + ref[i] = (byte) publicKeyX.getOctet(i); + } // End 'for' statement + Key.setEncodedParameter(ref); + // publicKeyY + Key = parameterList.get(2); + Key.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + Key.setNumberOfBits(publicKeyY.getLength() * Byte.SIZE); + ref = new byte[publicKeyY.getLength()]; + for (int i = 0; i < ref.length; i++) { + ref[i] = (byte) publicKeyY.getOctet(i); + } // End 'for' statement + Key.setEncodedParameter(ref); + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Byte.SIZE); + returnValue.setEncodedParameter(new byte[] { (byte)((result.getBoolean() == true) ? 0x01 : 0x00) } ); + + _logger.exiting("PluginAdapter", "exec_generateKeyPair", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_generateKeyPair + + private void exec_verifyWithEcdsaNistp256WithSha256(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_verifyWithEcdsaNistp256WithSha256"); + + // Execute the function + _logger.info(String.format("Setting parameter %s", parameterList.get(0).getParameterName())); + byte[] value = parameterList.get(0).getEncodedParameter(); + OctetstringValue toBeVerifiedData = (OctetstringValue) TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance(); + toBeVerifiedData.setLength(value.length); + for (int i = 0; i < toBeVerifiedData.getLength(); i++) { + toBeVerifiedData.setOctet(i, value[i]); + } // End 'for' statement + _logger.info(String.format("Setting parameter %s", parameterList.get(1).getParameterName())); + value = parameterList.get(1).getEncodedParameter(); + OctetstringValue signature = (OctetstringValue) TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance(); + signature.setLength(value.length); + for (int i = 0; i < signature.getLength(); i++) { + signature.setOctet(i, value[i]); + } // End 'for' statement + _logger.info(String.format("Setting parameter %s", parameterList.get(2).getParameterName())); + value = parameterList.get(2).getEncodedParameter(); + OctetstringValue ecdsaNistp256PublicKeyX = (OctetstringValue) TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance(); + ecdsaNistp256PublicKeyX.setLength(value.length); + for (int i = 0; i < ecdsaNistp256PublicKeyX.getLength(); i++) { + ecdsaNistp256PublicKeyX.setOctet(i, value[i]); + } // End 'for' statement + _logger.info(String.format("Setting parameter %s", parameterList.get(3).getParameterName())); + value = parameterList.get(3).getEncodedParameter(); + OctetstringValue ecdsaNistp256PublicKeyY = (OctetstringValue) TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance(); + ecdsaNistp256PublicKeyY.setLength(value.length); + for (int i = 0; i < ecdsaNistp256PublicKeyY.getLength(); i++) { + ecdsaNistp256PublicKeyY.setOctet(i, value[i]); + } // End 'for' statement + BooleanValue result = _extfuncsImpl.fx_verifyWithEcdsaNistp256WithSha256(toBeVerifiedData, signature, ecdsaNistp256PublicKeyX, ecdsaNistp256PublicKeyY); + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Byte.SIZE); + returnValue.setEncodedParameter(new byte[] { (byte)((result.getBoolean() == true) ? 0x01 : 0x00) } ); + + _logger.exiting("PluginAdapter", "exec_verifyWithEcdsaNistp256WithSha256", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_fx_verifyWithEcdsaNistp256WithSha256 + + private void exec_signWithEcdsaNistp256WithSha256(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_signWithEcdsaNistp256WithSha256"); + + // Execute the function + _logger.info(String.format("Setting parameter %s", parameterList.get(0).getParameterName())); + byte[] value = parameterList.get(0).getEncodedParameter(); + OctetstringValue toBeSignedData = (OctetstringValue) TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance(); + toBeSignedData.setLength(value.length); + for (int i = 0; i < toBeSignedData.getLength(); i++) { + toBeSignedData.setOctet(i, value[i]); + } // End 'for' statement + _logger.info(String.format("Setting parameter %s", parameterList.get(1).getParameterName())); + value = parameterList.get(1).getEncodedParameter(); + OctetstringValue privateKey = (OctetstringValue) TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance(); + privateKey.setLength(value.length); + for (int i = 0; i < privateKey.getLength(); i++) { + privateKey.setOctet(i, value[i]); + } // End 'for' statement +// IntegerValueEx privateKey = (IntegerValueEx) TciProvider.getInstance().getTciCDRequired().getInteger().newInstance(); +// privateKey.setInt64(ByteHelper.byteArrayToLong(value)); + OctetstringValue result = _extfuncsImpl.fx_signWithEcdsaNistp256WithSha256(toBeSignedData, privateKey); + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(result.getLength() * Byte.SIZE); + value = new byte[result.getLength()]; + for (int i = 0; i < value.length; i++) { + value[i] = (byte) result.getOctet(i); + } // End 'for' statement + returnValue.setEncodedParameter(value); + + _logger.exiting("PluginAdapter", "exec_signWithEcdsaNistp256WithSha256", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_signWithEcdsaNistp256WithSha256 + + private void exec_hashWithSha256(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_hashWithSha256"); + + // Execute the function + _logger.info(String.format("Setting parameter %s", parameterList.get(0).getParameterName())); + byte[] value = parameterList.get(0).getEncodedParameter(); + OctetstringValue toBeHashedData = (OctetstringValue) TciProvider.getInstance().getTciCDRequired().getOctetstring().newInstance(); + toBeHashedData.setLength(value.length); + for (int i = 0; i < toBeHashedData.getLength(); i++) { + toBeHashedData.setOctet(i, value[i]); + } // End 'for' statement + OctetstringValue result = _extfuncsImpl.fx_hashWithSha256(toBeHashedData); + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(result.getLength() * Byte.SIZE); +// System.out.println("Result length = " + result.getLength()); + value = new byte[result.getLength()]; + for (int i = 0; i < value.length; i++) { + value[i] = (byte) result.getOctet(i); + } // End 'for' statement + returnValue.setEncodedParameter(value); + + _logger.exiting("PluginAdapter", "exec_hashWithSha256", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_hashWithSha256 + + private void exec_dms2dd(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_dms2dd"); + + // Prepare arguments + ITciCDWrapper wrapper = TciCDWrapperFactory.getTciCDInstance(); + IntegerValue degrees = wrapper.setInteger(new BigInteger(parameterList.get(0).getEncodedParameter())); + IntegerValue minutes = wrapper.setInteger(new BigInteger(parameterList.get(1).getEncodedParameter())); + FloatValue seconds = wrapper.getFloat(); + seconds.setFloat(ByteHelper.byteArrayToFloat(parameterList.get(2).getEncodedParameter())); + OctetstringValue latlon = wrapper.getOctetstring(); + latlon.setLength(1); + latlon.setOctet(0, parameterList.get(3).getEncodedParameter()[0]); + FloatValue result = _extfuncsImpl.fx_dms2dd(degrees, minutes, seconds, latlon); + + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Float.SIZE); + returnValue.setEncodedParameter(ByteHelper.floatToByteArray(result.getFloat())); + + _logger.exiting("PluginAdapter", "exec_dms2dd", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_dms2dd + + private void exec_isValidPolygonalRegion(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_isValidPolygonalRegion"); + + // Decode region parameter + ITciCDWrapper wrapper = TciCDWrapperFactory.getTciCDInstance(); + RecordOfValue region = wrapper.getRecordOfValue("LibItsSecurity_TypesAndValues.PolygonalRegion"); + byte[] value = parameterList.get(0).getEncodedParameter(); + byte length = value[0]; + int offset = 1; + while (offset < length) { // TODO Create a method to fill PolygonRegions + // WGS84 Latitude + int latitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + // WGS84 Longitude + int longitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + RecordValue twoDLocation = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.TwoDLocation"); + twoDLocation.setField("latitude", wrapper.setInteger(latitude)); + twoDLocation.setField("longitude", wrapper.setInteger(longitude)); + } + // Execute the function + BooleanValue result = _extfuncsImpl.fx_isValidPolygonalRegion(region); + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Byte.SIZE); + returnValue.setEncodedParameter(new byte[] { (byte)((result.getBoolean() == true) ? 0x01 : 0x00) }); + + _logger.exiting("PluginAdapter", "exec_isValidPolygonalRegion", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_isValidPolygonalRegion + + private void exec_isPolygonalRegionInside(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_isPolygonalRegionInside"); + + // Decode parent parameter +// ByteHelper.dump("exec_isPolygonalRegionInside: ", parameterList.get(0).getEncodedParameter()); + // Execute the function + ITciCDWrapper wrapper = TciCDWrapperFactory.getTciCDInstance(); + RecordOfValue parent = wrapper.getRecordOfValue("LibItsSecurity_TypesAndValues.PolygonalRegion"); + byte[] value = parameterList.get(0).getEncodedParameter(); + byte length = value[0]; + int offset = 1; + while (offset < length) { // TODO Create a method to fill PolygonRegions + // WGS84 Latitude + int latitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + // WGS84 Longitude + int longitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + RecordValue twoDLocation = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.TwoDLocation"); + twoDLocation.setField("latitude", wrapper.setInteger(latitude)); + twoDLocation.setField("longitude", wrapper.setInteger(longitude)); + parent.appendField(twoDLocation); + } // End of 'while' statement + // Decode region parameter + RecordOfValue region = wrapper.getRecordOfValue("LibItsSecurity_TypesAndValues.PolygonalRegion"); + value = ByteHelper.extract(parameterList.get(0).getEncodedParameter(), offset, parameterList.get(0).getEncodedParameter().length - offset); + length = value[0]; + offset = 1; + while (offset < length) { // TODO Create a method to fill PolygonRegions + // WGS84 Latitude + int latitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + // WGS84 Longitude + int longitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + RecordValue twoDLocation = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.TwoDLocation"); + twoDLocation.setField("latitude", wrapper.setInteger(latitude)); + twoDLocation.setField("longitude", wrapper.setInteger(longitude)); + region.appendField(twoDLocation); + } // End of 'while' statement + // Execute the function + BooleanValue result = _extfuncsImpl.fx_isPolygonalRegionInside(parent, region); + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Byte.SIZE); + returnValue.setEncodedParameter(new byte[] { (byte)((result.getBoolean() == true) ? 0x01 : 0x00) }); + + _logger.exiting("PluginAdapter", "exec_isPolygonalRegionInside", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_isPolygonalRegionInside + + private void exec_isLocationInsideCircularRegion(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_isLocationInsideCircularRegion"); + + // Decode rectangularRegions parameter +// ByteHelper.dump("exec_isLocationInsideCircularRegion: ", parameterList.get(0).getEncodedParameter()); + ITciCDWrapper wrapper = TciCDWrapperFactory.getTciCDInstance(); + byte[] value = parameterList.get(0).getEncodedParameter(); + int offset = 0; + // Center + RecordValue center = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.TwoDLocation"); + // WGS84 Latitude + int latitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + // WGS84 Longitude + int longitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + center.setField("latitude", wrapper.setInteger(latitude)); + center.setField("longitude", wrapper.setInteger(longitude)); + + // Radius + int radius = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Short.SIZE / Byte.SIZE)); + + RecordValue circularRegion = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.CircularRegion"); + circularRegion.setField("center", center); + circularRegion.setField("radius", wrapper.setInteger(radius)); + // Decode location parameter +// ByteHelper.dump("exec_isLocationInsideCircularRegion: ", parameterList.get(1).getEncodedParameter()); + value = parameterList.get(1).getEncodedParameter(); + offset = 0; + // WGS84 Latitude + latitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + // WGS84 Longitude + longitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + RecordValue location = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.ThreeDLocation"); + location.setField("latitude", wrapper.setInteger(latitude)); + location.setField("longitude", wrapper.setInteger(longitude)); + OctetstringValue elevation = wrapper.getOctetstring(); + elevation.setLength(2); + elevation.setOctet(0, 0x00); elevation.setOctet(1, 0x00); + location.setField("elevation", elevation); + // Execute the function + BooleanValue result = _extfuncsImpl.fx_isLocationInsideCircularRegion(circularRegion, location); + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Byte.SIZE); + returnValue.setEncodedParameter(new byte[] { (byte)((result.getBoolean() == true) ? 0x01 : 0x00) }); + + _logger.exiting("PluginAdapter", "exec_isLocationInsideCircularRegion", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_isLocationInsideCircularRegion + + private void exec_isLocationInsideRectangularRegion(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_isLocationInsideRectangularRegion"); + + // Decode rectangularRegions parameter +// ByteHelper.dump("exec_isLocationInsidePolygonalRegion: ", parameterList.get(0).getEncodedParameter()); + ITciCDWrapper wrapper = TciCDWrapperFactory.getTciCDInstance(); + RecordOfValue rectangularRegions = wrapper.getRecordOfValue("LibItsSecurity_TypesAndValues.RectangularRegions"); + byte[] value = parameterList.get(0).getEncodedParameter(); + byte length = value[0]; + int offset = 1; + while (offset < length) { // TODO Create a method to fill RectangularRegions + // northwest + RecordValue northwest = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.TwoDLocation"); + // WGS84 Latitude + int latitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + // WGS84 Longitude + int longitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + northwest.setField("latitude", wrapper.setInteger(latitude)); + northwest.setField("longitude", wrapper.setInteger(longitude)); + + // southeast + RecordValue southeast = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.TwoDLocation"); + // WGS84 Latitude + latitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + // WGS84 Longitude + longitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + southeast.setField("latitude", wrapper.setInteger(latitude)); + southeast.setField("longitude", wrapper.setInteger(longitude)); + + RecordValue rectangularRegion = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.RectangularRegion"); + rectangularRegion.setField("northwest", northwest); + rectangularRegion.setField("southeast", southeast); + + rectangularRegions.appendField(rectangularRegion); + } // End of 'while' statement + // Decode location parameter +// ByteHelper.dump("exec_isLocationInsidePolygonalRegion: ", parameterList.get(1).getEncodedParameter()); + value = parameterList.get(1).getEncodedParameter(); + offset = 0; + // WGS84 Latitude + int latitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + // WGS84 Longitude + int longitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + RecordValue location = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.ThreeDLocation"); + location.setField("latitude", wrapper.setInteger(latitude)); + location.setField("longitude", wrapper.setInteger(longitude)); + OctetstringValue elevation = wrapper.getOctetstring(); + elevation.setLength(2); + elevation.setOctet(0, 0x00); elevation.setOctet(1, 0x00); + location.setField("elevation", elevation); + // Execute the function + BooleanValue result = _extfuncsImpl.fx_isLocationInsideRectangularRegion(rectangularRegions, location); + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Byte.SIZE); + returnValue.setEncodedParameter(new byte[] { (byte)((result.getBoolean() == true) ? 0x01 : 0x00) }); + + _logger.exiting("PluginAdapter", "exec_isLocationInsideRectangularRegion", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_isLocationInsideRectangularRegion + + private void exec_isLocationInsidePolygonalRegion(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_isLocationInsidePolygonalRegion"); + +// ByteHelper.dump("exec_isLocationInsidePolygonalRegion: ", parameterList.get(0).getEncodedParameter()); + // Execute the function + ITciCDWrapper wrapper = TciCDWrapperFactory.getTciCDInstance(); + RecordOfValue polygonalArea = wrapper.getRecordOfValue("LibItsSecurity_TypesAndValues.PolygonalRegion"); + byte[] value = parameterList.get(0).getEncodedParameter(); + byte length = value[0]; + int offset = 1; + while (offset < length) { // TODO Create a method to fill PolygonRegions + // WGS84 Latitude + int latitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + // WGS84 Longitude + int longitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + RecordValue twoDLocation = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.TwoDLocation"); + twoDLocation.setField("latitude", wrapper.setInteger(latitude)); + twoDLocation.setField("longitude", wrapper.setInteger(longitude)); + polygonalArea.appendField(twoDLocation); + } // End of 'while' statement +// ByteHelper.dump("exec_isLocationInsidePolygonalRegion: ", parameterList.get(1).getEncodedParameter()); + value = parameterList.get(1).getEncodedParameter(); + offset = 0; + // WGS84 Latitude + int latitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + // WGS84 Longitude + int longitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + RecordValue location = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.ThreeDLocation"); + location.setField("latitude", wrapper.setInteger(latitude)); + location.setField("longitude", wrapper.setInteger(longitude)); + OctetstringValue elevation = wrapper.getOctetstring(); + elevation.setLength(2); + elevation.setOctet(0, 0x00); elevation.setOctet(1, 0x00); + location.setField("elevation", elevation); + BooleanValue result = _extfuncsImpl.fx_isLocationInsidePolygonalRegion(polygonalArea, location); + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Byte.SIZE); + returnValue.setEncodedParameter(new byte[] { (byte)((result.getBoolean() == true) ? 0x01 : 0x00) }); + + _logger.exiting("PluginAdapter", "exec_isLocationInsidePolygonalRegion", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_isLocationInsidePolygonalRegion + + private void exec_isLocationInsideIdentifiedRegion(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_isLocationInsideIdentifiedRegion"); + + // Decode rectangularRegions parameter +// ByteHelper.dump("exec_isLocationInsideIdentifiedRegion: ", parameterList.get(0).getEncodedParameter()); + ITciCDWrapper wrapper = TciCDWrapperFactory.getTciCDInstance(); + byte[] value = parameterList.get(0).getEncodedParameter(); + int offset = 0; + // RegionDictionary + EnumeratedValue region_dictionary = wrapper.getEnumValue("LibItsSecurity_TypesAndValues.RegionDictionary"); + region_dictionary.setInt(value[offset++]); + // region_identifier + int region_identifier = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Short.SIZE / Byte.SIZE)); + offset += Short.SIZE / Byte.SIZE; + // local_region + int local_region; + if ((value[offset] & 0x80) == 0x00) { // One byte length + local_region = value[offset]; + } else { + // TODO Process it as IntX, not as 4 bytes integer + value[offset] &= 0x7f; + local_region = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Short.SIZE / Byte.SIZE)); + } + RecordValue identifiedRegion = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.IdentifiedRegion"); + identifiedRegion.setField("region_dictionary", region_dictionary); + identifiedRegion.setField("region_identifier", wrapper.setInteger(region_identifier)); + identifiedRegion.setField("local_region", wrapper.setInteger(local_region)); + + // Decode location parameter +// ByteHelper.dump("exec_isLocationInsideIdentifiedRegion: ", parameterList.get(1).getEncodedParameter()); + value = parameterList.get(1).getEncodedParameter(); + offset = 0; + // WGS84 Latitude + int latitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + // WGS84 Longitude + int longitude = ByteHelper.byteArrayToInt(ByteHelper.extract(value, offset, Integer.SIZE / Byte.SIZE)); + offset += Integer.SIZE / Byte.SIZE; + RecordValue location = wrapper.getRecordValue("LibItsSecurity_TypesAndValues.ThreeDLocation"); + location.setField("latitude", wrapper.setInteger(latitude)); + location.setField("longitude", wrapper.setInteger(longitude)); + OctetstringValue elevation = wrapper.getOctetstring(); + elevation.setLength(2); + elevation.setOctet(0, 0x00); elevation.setOctet(1, 0x00); + location.setField("elevation", elevation); + // Execute the function + BooleanValue result = _extfuncsImpl.fx_isLocationInsideIdentifiedRegion(identifiedRegion, location); + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Byte.SIZE); + returnValue.setEncodedParameter(new byte[] { (byte)((result.getBoolean() == true) ? 0x01 : 0x00) }); + + _logger.exiting("PluginAdapter", "exec_isLocationInsideIdentifiedRegion", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_isLocationInsideIdentifiedRegion + + private void exec_loadCertificates(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_loadCertificates"); + + // Decode parameter +// ByteHelper.dump("exec_loadCertificates: ", parameterList.get(0).getEncodedParameter()); + CharstringValue rootDirectory = TciCDWrapperFactory.getTciCDInstance().getCharstringValue(); + String str = new String(parameterList.get(0).getEncodedParameter()); + rootDirectory.setString(str); + +// ByteHelper.dump("exec_loadCertificates: ", parameterList.get(1).getEncodedParameter()); + CharstringValue configId = TciCDWrapperFactory.getTciCDInstance().getCharstringValue(); + str = new String(parameterList.get(1).getEncodedParameter()); + configId.setString(str); + + // Execute the function + BooleanValue result = _extfuncsImpl.fx_loadCertificates(rootDirectory, configId); + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Byte.SIZE); + returnValue.setEncodedParameter(new byte[] { (byte)((result.getBoolean() == true) ? 0x01 : 0x00) }); + + _logger.exiting("PluginAdapter", "exec_loadCertificates", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_parseIpv6Address + + private void exec_unloadCertificates(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_unloadCertificates"); + + // Execute the function + BooleanValue result = _extfuncsImpl.fx_unloadCertificates(); + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Byte.SIZE); + returnValue.setEncodedParameter(new byte[] { (byte)((result.getBoolean() == true) ? 0x01 : 0x00) }); + + _logger.exiting("PluginAdapter", "exec_unloadCertificates", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_parseIpv6Address + + private void exec_readCertificate(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_readCertificate"); + + // Decode parameter +// ByteHelper.dump("exec_readPrivateKeys: ", parameterList.get(0).getEncodedParameter()); + CharstringValue certificateId = TciCDWrapperFactory.getTciCDInstance().getCharstringValue(); + String str = new String(parameterList.get(0).getEncodedParameter()); + certificateId.setString(str); + + OctetstringValue certificate = TciCDWrapperFactory.getTciCDInstance().getOctetstring(); + + // Execute the function + BooleanValue result = _extfuncsImpl.fx_readCertificate(certificateId, certificate); + + parameterList.get(1).setNumberOfBits(certificate.getLength() * Byte.SIZE); + byte[] value = new byte[certificate.getLength()]; + for (int i = 0; i < value.length; i++) { + value[i] = (byte) certificate.getOctet(i); + }// End of 'for'statement + parameterList.get(1).setEncodedParameter(value); + + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Byte.SIZE); + returnValue.setEncodedParameter(new byte[] { (byte)((result.getBoolean() == true) ? 0x01 : 0x00) }); + + _logger.exiting("PluginAdapter", "exec_readCertificate", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_parseIpv6Address + + private void exec_readPrivateKeys(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_readPrivateKeys"); + + // Decode parameter +// ByteHelper.dump("exec_readPrivateKeys: ", parameterList.get(0).getEncodedParameter()); + CharstringValue keysId = TciCDWrapperFactory.getTciCDInstance().getCharstringValue(); + String str = new String(parameterList.get(0).getEncodedParameter()); + keysId.setString(str); + + + OctetstringValue signingPrivateKey = TciCDWrapperFactory.getTciCDInstance().getOctetstring(); + OctetstringValue encryptPrivateKey = TciCDWrapperFactory.getTciCDInstance().getOctetstring(); + + // Execute the function + BooleanValue result = _extfuncsImpl.fx_readPrivateKeys(keysId, signingPrivateKey, encryptPrivateKey); + + parameterList.get(1).setNumberOfBits(signingPrivateKey.getLength() * Byte.SIZE); + byte[] value = new byte[signingPrivateKey.getLength()]; + for (int i = 0; i < value.length; i++) { + value[i] = (byte) signingPrivateKey.getOctet(i); + }// End of 'for'statement + parameterList.get(1).setEncodedParameter(value); + + parameterList.get(2).setNumberOfBits(encryptPrivateKey.getLength() * Byte.SIZE); + value = new byte[encryptPrivateKey.getLength()]; + for (int i = 0; i < value.length; i++) { + value[i] = (byte) encryptPrivateKey.getOctet(i); + }// End of 'for'statement + parameterList.get(2).setEncodedParameter(value); + + // Return code + returnValue.setParameterPassingMode(TriParameterPassingMode.TRI_OUT); + returnValue.setNumberOfBits(Byte.SIZE); + returnValue.setEncodedParameter(new byte[] { (byte)((result.getBoolean() == true) ? 0x01 : 0x00) }); + + _logger.exiting("PluginAdapter", "exec_readPrivateKeys", ByteHelper.byteArrayToString(returnValue.getEncodedParameter())); + } // End of method exec_parseIpv6Address + + private void exec_parseIpv6Address(TriParameterList parameterList, TriParameter returnValue) { + _logger.entering("PluginAdapter", "exec_parseIpv6Address"); + + } // End of method exec_parseIpv6Address + + @Override + public TriStatus triBeginWait(long arg0, TriComponentId arg1) { + throw new RuntimeException(); + } + + @Override + public TriStatus triNextSampling(long arg0, TriPortId arg1) { + throw new RuntimeException(); + } + + @Override + public TriStatus triReadClock(TriLong arg0) { + throw new RuntimeException(); + } + + @Override + public TriStatus triStartClock(long arg0) { + throw new RuntimeException(); + } + + @Override + public void triSAErrorReq(String arg0) { + throw new RuntimeException(); + } + + @Override + public TriStatus triGetStreamValue(TriComponentId arg0, TriPortId arg1, TriAddress arg2, TriMessage arg3) { + throw new RuntimeException(); + } + + @Override + public TriStatus triSetStreamValue(TriComponentId arg0, TriPortId arg1, TriAddress arg2, TriMessage arg3) { + throw new RuntimeException(); + } } // End of class PluginAdapter diff --git a/javasrc/tool/org/etsi/its/tool/elvior/res/codec.properties b/javasrc/tool/org/etsi/its/tool/elvior/res/codec.properties index 101f09882..d64f57f6d 100644 --- a/javasrc/tool/org/etsi/its/tool/elvior/res/codec.properties +++ b/javasrc/tool/org/etsi/its/tool/elvior/res/codec.properties @@ -1,5 +1,5 @@ # Debug level - Authorized values: OFF, ALL, INFO, SEVERE -DEBUG_ENABLED=ALL +DEBUG_ENABLED=OFF ASN.1Codecs=CAM,DENM,CDD CAM=LibItsCam_asn1,org.etsi.its.tool.elvior.LibItsCam_asn1 diff --git a/javasrc/tool/org/etsi/its/tool/elvior/res/ta.properties b/javasrc/tool/org/etsi/its/tool/elvior/res/ta.properties index 3fd9593c1..0a78eb59d 100644 --- a/javasrc/tool/org/etsi/its/tool/elvior/res/ta.properties +++ b/javasrc/tool/org/etsi/its/tool/elvior/res/ta.properties @@ -1,11 +1,11 @@ # Debug level - Authorized values: OFF, ALL, INFO, SEVERE -DEBUG_ENABLED=ALL +DEBUG_ENABLED=OFF # Define the port/layer configuration for CAM camPort=BTP/GN/ETH # Define the port/layer configuration for DENM denmPort=BTP/GN/ETH # Define the port/layer configuration for BTP -btpPort=Debug +btpPort=GN/ETH # Define the port/layer configuration for GeoNetworking geoNetworkingPort=ETH # Define the port/layer configuration for GeoNetworking over IPv6 @@ -14,37 +14,44 @@ ipv6OverGeoNetworkingPort=Debug #fntpPort=FNTP/ETH fntpPort=FNTP/UdpIp # Define the port/layer configuration for CALM FSAP -fsapPort=FSAP/ETH +fsapPort=FSAP/UdpIp fsapPort=FSAP/UdpIp -UpperTesterSettings=192.168.122.131:2222 +#UpperTesterSettings=192.168.1.44:1501 +UpperTesterSettings=172.28.0.33:1501 # Peer ITS station -LinkLayer_Peer=DEADBEEF000A +LinkLayer_Peer=BABEBABE0099 # Define the MAC address of the Ethernet interface connected to the IUT device # Home laptop VMWare MAC address -LocalEthernetMAC=005056C00008 +#LocalEthernetMAC=005056C00008 # Home laptop MAC address -#LocalEthernetMAC=4C80938EDB27 +LocalEthernetMAC=4C80938EDB27 # ETSI computer MAC address #LocalEthernetMAC=0022191B7FDB # Define the Ethernet type value used by the IUT IutEthernetTypeValue=0x8947 # Node Ethernet addresses -LinkLayer_MTC=DEADBEEF0002 +LinkLayer_MTC=BABEBABE0000 # Link-Layer address of component NodeA -LinkLayer_NodeA=DEADBEEF0001 +LinkLayer_NodeA=BABEBABE0001 # Link-Layer address of component NodeB -LinkLayer_NodeB=DEADBEEF0002 +LinkLayer_NodeB=BABEBABE0002 # Link-Layer address of component NodeC -LinkLayer_NodeC=DEADBEEF0003 +LinkLayer_NodeC=BABEBABE0003 # Link-Layer address of component NodeD -LinkLayer_NodeD=DEADBEEF0004 +LinkLayer_NodeD=BABEBABE0004 # Interval between each beacon sent by TS (ms) TsBeaconInterval=1000 # Latitude of Test System -TsLatitude=436175790 +TsLatitude=7000 # Longitude of Test System -TsLongitude=70546480 +TsLongitude=520000 +# Secured mode status +TsSecuredMode=false +# Secured root path to access certificates and private keys +TsSecuredPath="" +# Secured configuration identifier +TsSecuredConfiId=cfg01 diff --git a/javasrc/tool/org/etsi/its/tool/testingtech/ExternalFunctionsPluginProvider.java b/javasrc/tool/org/etsi/its/tool/testingtech/ExternalFunctionsPluginProvider.java index a131985f3..1ac1ddf3b 100644 --- a/javasrc/tool/org/etsi/its/tool/testingtech/ExternalFunctionsPluginProvider.java +++ b/javasrc/tool/org/etsi/its/tool/testingtech/ExternalFunctionsPluginProvider.java @@ -1,6 +1,6 @@ /** - * @author STF 424_ITS_Test_Platform - * @version $id$ + * @author STF 424_ITS_Test_Platform + * @version $id$ */ package org.etsi.its.tool.testingtech; @@ -8,10 +8,13 @@ import org.etsi.codec.TciCDWrapperFactory; import org.etsi.its.extfunc.IItsExternalFunctionsProvider; import org.etsi.its.extfunc.ItsExternalFunctionsProvider; import org.etsi.tool.testingtech.TciCDWrapper; +import org.etsi.ttcn.tci.BooleanValue; import org.etsi.ttcn.tci.CharstringValue; 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 com.testingtech.ttcn.extension.ExternalFunctionsProvider; import com.testingtech.ttcn.tri.ExternalFunctionsDefinition; @@ -24,94 +27,94 @@ import de.tu_berlin.cs.uebb.muttcn.runtime.RB; */ public class ExternalFunctionsPluginProvider implements ExternalFunctionsProvider, ExternalFunctionsDefinition, IItsExternalFunctionsProvider { - /** - * Reference to the - */ - private IItsExternalFunctionsProvider _externalFunctionsPluginProvider; - - - /** - * Constructor - */ - public ExternalFunctionsPluginProvider() { - _externalFunctionsPluginProvider = null; - - } - - /** - * Constructor - * - * @param rb TTwb runtime reference - */ - public ExternalFunctionsPluginProvider(RB rb) { - TciCDWrapperFactory.getInstance().setImpl(new TciCDWrapper(rb)); - _externalFunctionsPluginProvider = (IItsExternalFunctionsProvider)new ItsExternalFunctionsProvider(); - - } - - /** - * Refer to TTwb developer's guide - */ - @Override - public ExternalFunctionsDefinition getExternalFunctions(RB rb) { - return new ExternalFunctionsPluginProvider(rb); - } - - /** - * This external function gets the current time - * @param pLatitudeA Latitude of node A - * @param pLongitudeA Longitude of node A - * @param pLatitudeB Latitude of node B - * @param pLongitudeB 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 FloatValue fx_computeDistance(IntegerValue pLatitudeA, - IntegerValue pLongitudeA, IntegerValue pLatitudeB, - IntegerValue pLongitudeB) { - return _externalFunctionsPluginProvider.fx_computeDistance(pLatitudeA, pLongitudeA, pLatitudeB, pLongitudeB); - } - - /** - * External function to compute a position using a reference position, a distance and an orientation - * @param pIutLongPosVector Reference position - * @param pDistance Distance to the reference position (in meter) - * @param pOrientation Direction of the computed position (0 to 359; 0 means North) - * @param pLatitude Computed position's latitude - * @param pLongitude 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 void fx_computePositionUsingDistance( - IntegerValue p_refLatitude, IntegerValue p_refLongitude, - IntegerValue pDistance, IntegerValue pOrientation, - IntegerValue pLatitude, IntegerValue pLongitude) { - _externalFunctionsPluginProvider.fx_computePositionUsingDistance(p_refLatitude, p_refLongitude, pDistance, pOrientation, pLatitude, pLongitude); - } + /** + * Reference to the + */ + private IItsExternalFunctionsProvider _externalFunctionsPluginProvider; + + + /** + * Constructor + */ + public ExternalFunctionsPluginProvider() { + _externalFunctionsPluginProvider = null; + + } + + /** + * Constructor + * + * @param rb TTwb runtime reference + */ + public ExternalFunctionsPluginProvider(RB rb) { + TciCDWrapperFactory.getInstance().setImpl(new TciCDWrapper(rb)); + _externalFunctionsPluginProvider = (IItsExternalFunctionsProvider)new ItsExternalFunctionsProvider(); + + } + + /** + * Refer to TTwb developer's guide + */ + @Override + public ExternalFunctionsDefinition getExternalFunctions(RB rb) { + return new ExternalFunctionsPluginProvider(rb); + } + + /** + * This external function gets the current time + * @param pLatitudeA Latitude of node A + * @param pLongitudeA Longitude of node A + * @param pLatitudeB Latitude of node B + * @param pLongitudeB 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 FloatValue fx_computeDistance(IntegerValue pLatitudeA, + IntegerValue pLongitudeA, IntegerValue pLatitudeB, + IntegerValue pLongitudeB) { + return _externalFunctionsPluginProvider.fx_computeDistance(pLatitudeA, pLongitudeA, pLatitudeB, pLongitudeB); + } + + /** + * External function to compute a position using a reference position, a distance and an orientation + * @param pIutLongPosVector Reference position + * @param pDistance Distance to the reference position (in meter) + * @param pOrientation Direction of the computed position (0 to 359; 0 means North) + * @param pLatitude Computed position's latitude + * @param pLongitude 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 void fx_computePositionUsingDistance( + IntegerValue p_refLatitude, IntegerValue p_refLongitude, + IntegerValue pDistance, IntegerValue pOrientation, + IntegerValue pLatitude, IntegerValue pLongitude) { + _externalFunctionsPluginProvider.fx_computePositionUsingDistance(p_refLatitude, p_refLongitude, pDistance, pOrientation, pLatitude, pLongitude); + } @Override public FloatValue fx_computeRadiusFromCircularArea(FloatValue p_squareMeters) { return _externalFunctionsPluginProvider.fx_computeRadiusFromCircularArea(p_squareMeters); } - /** - * This external function gets the current time - * @return The current time in Epoch format - * - * TTCN-3 signature: - * external function fx_getCurrentTime() return TimeStamp; - */ - @Override - public IntegerValue fx_getCurrentTime() { - return _externalFunctionsPluginProvider.fx_getCurrentTime(); - } - - /** + /** + * This external function gets the current time + * @return The current time in Epoch format + * + * TTCN-3 signature: + * external function fx_getCurrentTime() return TimeStamp; + */ + @Override + public IntegerValue fx_getCurrentTime() { + return _externalFunctionsPluginProvider.fx_getCurrentTime(); + } + + /** * External function to compute timestamp based on current time * @return Unix-Epoch-Time mod 2^32 * @@ -181,6 +184,113 @@ public class ExternalFunctionsPluginProvider implements ExternalFunctionsProvide @Override public OctetstringValue xf_parseIpv6Address(final CharstringValue p_textIpv6Address) { - return _externalFunctionsPluginProvider.xf_parseIpv6Address(p_textIpv6Address); + return _externalFunctionsPluginProvider.xf_parseIpv6Address(p_textIpv6Address); + } + + /** + * @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 + */ + @Override + public OctetstringValue fx_hashWithSha256(final OctetstringValue p_toBeHashedData) { + return _externalFunctionsPluginProvider.fx_hashWithSha256(p_toBeHashedData); + } + + /** + * @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 + */ + @Override + public OctetstringValue fx_signWithEcdsaNistp256WithSha256(final OctetstringValue p_toBeSignedData, final OctetstringValue p_privateKey) { + return _externalFunctionsPluginProvider.fx_signWithEcdsaNistp256WithSha256(p_toBeSignedData, p_privateKey); + } + + /** + * @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 + */ + @Override + public BooleanValue fx_verifyWithEcdsaNistp256WithSha256(final OctetstringValue p_toBeVerifiedData, final OctetstringValue p_signature, final OctetstringValue p_ecdsaNistp256PublicKeyX, final OctetstringValue p_ecdsaNistp256PublicKeyY) { + return _externalFunctionsPluginProvider.fx_verifyWithEcdsaNistp256WithSha256(p_toBeVerifiedData, p_signature, p_ecdsaNistp256PublicKeyX, p_ecdsaNistp256PublicKeyY); + } + + /** + * @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 + */ + @Override + public BooleanValue fx_generateKeyPair(OctetstringValue p_privateKey, OctetstringValue p_publicKeyX, OctetstringValue p_publicKeyY) { + return _externalFunctionsPluginProvider.fx_generateKeyPair(p_privateKey, p_publicKeyX, p_publicKeyY); + } + + /** + * @desc Check that given polygon doesn't have neither self-intersections nor holes. + * @param p_region Polygonal Region + * @return true on success, false otherwise + */ + @Override + public BooleanValue fx_isValidPolygonalRegion(RecordOfValue p_region) { + return _externalFunctionsPluginProvider.fx_isValidPolygonalRegion(p_region); + } + + @Override + public BooleanValue fx_isPolygonalRegionInside(RecordOfValue p_parent, RecordOfValue p_region) { + return _externalFunctionsPluginProvider.fx_isPolygonalRegionInside(p_parent, p_region); + } + + @Override + public BooleanValue fx_isLocationInsideCircularRegion(RecordValue p_region, RecordValue p_location) { + return _externalFunctionsPluginProvider.fx_isLocationInsideCircularRegion(p_region, p_location); + } + + @Override + public BooleanValue fx_isLocationInsideRectangularRegion(RecordOfValue p_region, RecordValue p_location) { + return _externalFunctionsPluginProvider.fx_isLocationInsideRectangularRegion(p_region, p_location); + } + + @Override + public BooleanValue fx_isLocationInsidePolygonalRegion(final RecordOfValue p_region, final RecordValue p_location) { + return _externalFunctionsPluginProvider.fx_isLocationInsidePolygonalRegion(p_region, p_location); + } + + @Override + public BooleanValue fx_isLocationInsideIdentifiedRegion(RecordValue p_region, RecordValue p_location) { + return _externalFunctionsPluginProvider.fx_isLocationInsideIdentifiedRegion(p_region, p_location); + } + + @Override + public FloatValue fx_dms2dd(IntegerValue p_degrees, IntegerValue p_minutes, FloatValue p_seconds, OctetstringValue p_latlon) { + return _externalFunctionsPluginProvider.fx_dms2dd(p_degrees, p_minutes, p_seconds, p_latlon); + } + + @Override + public BooleanValue fx_loadCertificates(CharstringValue p_rootDirectory, CharstringValue p_configId) { + return _externalFunctionsPluginProvider.fx_loadCertificates(p_rootDirectory, p_configId); } + + @Override + public BooleanValue fx_unloadCertificates() { + return _externalFunctionsPluginProvider.fx_unloadCertificates(); + } + + @Override + public BooleanValue fx_readCertificate(CharstringValue p_certificateName, OctetstringValue p_certificate) { + return _externalFunctionsPluginProvider.fx_readCertificate(p_certificateName, p_certificate); + } + + @Override + public BooleanValue fx_readPrivateKeys(CharstringValue p_certificateName, OctetstringValue p_signingPrivateKey, OctetstringValue p_encryptPrivateKey) { + return _externalFunctionsPluginProvider.fx_readPrivateKeys(p_certificateName, p_signingPrivateKey, p_encryptPrivateKey); + } + } diff --git a/javasrc/tool/org/etsi/its/tool/testingtech/Its_CodecProvider.java b/javasrc/tool/org/etsi/its/tool/testingtech/Its_CodecProvider.java index a6843ea0e..327e0e92f 100644 --- a/javasrc/tool/org/etsi/its/tool/testingtech/Its_CodecProvider.java +++ b/javasrc/tool/org/etsi/its/tool/testingtech/Its_CodecProvider.java @@ -5,16 +5,16 @@ */ package org.etsi.its.tool.testingtech; +import org.etsi.codec.ITciCDWrapper; +import org.etsi.codec.TciCDWrapperFactory; import org.etsi.tool.testingtech.TTWBCodecSupport; +import org.etsi.ttcn.codec.CodecFactory; +import org.etsi.ttcn.codec.MainCodec; import org.etsi.ttcn.tci.TciCDProvided; -import org.etsi.ttcn.tci.TciCDRequired; import org.etsi.ttcn.tci.Type; import org.etsi.ttcn.tci.Value; import org.etsi.ttcn.tri.TriMessage; -import org.etsi.ttcn.codec.CodecFactory; -import org.etsi.ttcn.codec.MainCodec; - import com.testingtech.ttcn.extension.CodecProvider; import com.testingtech.util.plugin.PluginInitException; @@ -24,33 +24,31 @@ import de.tu_berlin.cs.uebb.muttcn.runtime.RB; */ public class Its_CodecProvider implements CodecProvider { - /** - * This method provides the codec associated to the specified encoding identifier - * - * @param rb TTwb Runtime reference - * @param encodingName The name of the encoding, specified by the TTCN-3 key words 'with/encode' - * @return The codec associated to the specified encoding identifier - */ - @Override + /** + * This method provides the codec associated to the specified encoding identifier + * + * @param rb TTwb Runtime reference + * @param encodingName The name of the encoding, specified by the TTCN-3 key words 'with/encode' + * @return The codec associated to the specified encoding identifier + */ + @Override public TciCDProvided getCodec(RB rb, String encodingName) throws PluginInitException { - - cdReq = rb.getTciCDRequired(); - - // Register External codecs - CodecFactory cf = CodecFactory.getInstance(); - TTWBCodecSupport cs = new TTWBCodecSupport(rb); + + // Register External codecs + CodecFactory cf = CodecFactory.getInstance(); + TTWBCodecSupport cs = new TTWBCodecSupport(rb); cf.setExternalCodec("LibItsCam_asn1", cs.getCodec("LibItsCam_asn1")); cf.setExternalCodec("LibItsDenm_asn1", cs.getCodec("LibItsDenm_asn1")); //TODO: add V2G external codecs (xsd) //TODO: Yann add CALM external codecs (ASN.1) - return new Codec(); - } + return new Codec(); + } - private class Codec implements TciCDProvided { + private class Codec implements TciCDProvided { @Override public Value decode(TriMessage message, Type decodingHypothesis) { - MainCodec codec = new MainCodec(cdReq); + MainCodec codec = new MainCodec((ITciCDWrapper) TciCDWrapperFactory.getTciCDInstance()); Value v = null; try { v = codec.triDecode(message, decodingHypothesis); @@ -63,7 +61,7 @@ public class Its_CodecProvider implements CodecProvider { @Override public TriMessage encode(Value value) { - MainCodec codec = new MainCodec(cdReq); + MainCodec codec = new MainCodec((ITciCDWrapper) TciCDWrapperFactory.getTciCDInstance()); TriMessage m = null; try { m = codec.triEncode(value); @@ -72,8 +70,6 @@ public class Its_CodecProvider implements CodecProvider { e.printStackTrace(); } return m; - } - } - - private TciCDRequired cdReq; + } + } } diff --git a/javasrc/tool/org/etsi/tool/elvior/TciCDWrapper.java b/javasrc/tool/org/etsi/tool/elvior/TciCDWrapper.java index bb22e832b..e37dc1728 100644 --- a/javasrc/tool/org/etsi/tool/elvior/TciCDWrapper.java +++ b/javasrc/tool/org/etsi/tool/elvior/TciCDWrapper.java @@ -9,9 +9,14 @@ import java.math.BigInteger; import org.elvior.ttcn.tritci.IntegerValueEx; import org.elvior.ttcn.tritci.TciProvider; import org.etsi.codec.ITciCDWrapper; +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 org.etsi.ttcn.tci.TciCDRequired; import org.etsi.ttcn.tci.Type; import org.etsi.ttcn.tci.Value; @@ -31,33 +36,59 @@ public class TciCDWrapper implements ITciCDWrapper { } @Override - public IntegerValue getInteger() { - return (IntegerValue)_tciFactory.getInteger().newInstance(); + public IntegerValue setInteger(final Integer value) { + IntegerValue iv = (IntegerValue)_tciFactory.getInteger().newInstance(); + iv.setInteger(value); + return iv; } @Override - public IntegerValue getBigInteger(final BigInteger bigInt) { - System.out.println(">>> getBigInteger" + bigInt); - IntegerValueEx bi = (IntegerValueEx) _tciFactory.getTypeForName("org.elvior.ttcn.tritci.IntegerValueEx"); // FIXME To be solved with Janek + public int getInteger(final IntegerValue iv) { + return iv.getInteger(); + } + + @Override + public IntegerValue setInteger(final BigInteger value) { +// System.out.println(">>> getBigInteger: " + value); + IntegerValueEx bi = (IntegerValueEx) _tciFactory.getInteger().newInstance(); //_tciFactory.getTypeForName("org.elvior.ttcn.tritci.IntegerValueEx"); if (bi != null) { - System.out.println("getBigInteger: then"); - bi.setInt64(bigInt.longValue()); - System.out.println("getBigInteger: bi=" + bi); +// System.out.println("getBigInteger: then"); + bi.setInt64(value.longValue()); +// System.out.println("getBigInteger: bi=" + bi.getInt64()); return (IntegerValue)bi; } else { - System.out.println("getBigInteger: else"); +// System.out.println("getBigInteger: else"); IntegerValue i = (IntegerValue) _tciFactory.getInteger().newInstance(); - System.out.println("getBigInteger: i=" + i); - i.setInteger(bigInt.intValue()); +// System.out.println("getBigInteger: i=" + i); + i.setInteger(value.intValue()); return i; } } + @Override + public void setInteger(BigInteger value, IntegerValue setInt) { + ((IntegerValueEx)setInt).setInt64(value.longValue()); + } + + @Override + public long getBigInteger(final IntegerValue iv) { + return ((IntegerValueEx)iv).getInt64(); + } + @Override public OctetstringValue getOctetstring() { return (OctetstringValue)_tciFactory.getOctetstring().newInstance(); } + /** Constructs and returns a basic TTCN-3 string type + * + * @return An instance of Type representing a TTCN-3 string type + */ + @Override + public CharstringValue getCharstringValue() { + return (CharstringValue)_tciFactory.getCharstring().newInstance(); + } + @Override public FloatValue getFloat() { return (FloatValue)_tciFactory.getFloat().newInstance(); @@ -65,32 +96,51 @@ public class TciCDWrapper implements ITciCDWrapper { @Override public Value getUnionValue(final Type decodingHypothesis, final String variantName) { -// System.out.println(">>> getUnionValue: " + decodingHypothesis.getName()); +// System.out.println(">>> getUnionValue: " + decodingHypothesis.getName() + ", " + variantName); String variantTypeName = decodingHypothesis.getDefiningModule().getModuleName() + "." + decodingHypothesis.getName() + "." + variantName; -// System.out.println("getUnionValue: variantTypeName=" + variantTypeName); +// System.out.println("variantTypeName is " + variantTypeName); Type variantType = _tciFactory.getTypeForName(variantTypeName); if(variantType != null) { -// System.out.println("Variant Type name is: " + variantType.getName()); -// String moduleBase = variantType.getDefiningModule().getBaseName(); -// System.out.println("Variant Type DefiningModule.BaseName is: " + variantType.getName()); -// String moduleObj = variantType.getDefiningModule().getModuleName(); -// System.out.println("Variant Type DefiningModule.ModuleName is: " + variantType.getName()); Value testVal = variantType.newInstance(); if(testVal != null) { // System.out.println("Variant value has been created."); return testVal; } - } else { - System.err.println("variantType is null"); } + System.err.println("variantType is null"); + System.out.println("Variant value hasn't been created."); return null; } @Override public Type getTypeForName(final String type) { - return TciProvider.getInstance().getTciCDRequired().getTypeForName(type); +// return TciProvider.getInstance().getTciCDRequired().getTypeForName(type); +// System.out.println("TciCDWrapper.getTypeForName" + type); + Type originalType = TciProvider.getInstance().getTciCDRequired().getTypeForName(type); +// System.out.println("TciCDWrapper.getTypeForName" + originalType.getName()); + return originalType; } // End of method getTypeForName + @Override + public BooleanValue getBoolean() { + return (BooleanValue)_tciFactory.getBoolean().newInstance(); + } + + @Override + public EnumeratedValue getEnumValue(String typeName) { + return (EnumeratedValue)_tciFactory.getTypeForName(typeName).newInstance(); + } + + @Override + public RecordValue getRecordValue(final String typeName) { + return (RecordValue)_tciFactory.getTypeForName(typeName).newInstance(); + } + + @Override + public RecordOfValue getRecordOfValue(final String typeName) { + return (RecordOfValue)_tciFactory.getTypeForName(typeName).newInstance(); + } + } // End of class TciCDWrapper diff --git a/javasrc/tool/org/etsi/tool/testingtech/TciCDWrapper.java b/javasrc/tool/org/etsi/tool/testingtech/TciCDWrapper.java index 65d2cb9ac..be61c1c83 100644 --- a/javasrc/tool/org/etsi/tool/testingtech/TciCDWrapper.java +++ b/javasrc/tool/org/etsi/tool/testingtech/TciCDWrapper.java @@ -1,15 +1,20 @@ /** - * @author STF 424_ITS_Test_Platform - * @version $id$ + * @author STF 424_ITS_Test_Platform + * @version $id$ */ package org.etsi.tool.testingtech; import java.math.BigInteger; import org.etsi.codec.ITciCDWrapper; +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 org.etsi.ttcn.tci.Type; import org.etsi.ttcn.tci.Value; @@ -23,63 +28,116 @@ import de.tu_berlin.cs.uebb.muttcn.runtime.RB; */ public class TciCDWrapper implements ITciCDWrapper { - /** - * RuntimeBehavior instance reference - */ - private RB _rb; - - /** - * Specialized ctor - * @param rb TTCN-3 runtime reference - */ - public TciCDWrapper(final RB rb) { - _rb = rb; - } - - /** Constructs and returns a basic TTCN-3 float type - * - * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.3 getFloat - * @return An instance of Type representing a TTCN-3 float type - */ - @Override - public FloatValue getFloat() { - return (FloatValue)_rb.getTciCDRequired().getFloat().newInstance(); - } - - /** Constructs and returns a basic TTCN-3 integer type - * - * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getInteger - * @return An instance of Type representing a TTCN-3 integer type - */ - @Override - public IntegerValue getInteger() { - return (IntegerValue)_rb.getTciCDRequired().getInteger().newInstance(); - } - - /** Constructs and returns a basic TTCN-3 integer type - * - * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getInteger - * @return An instance of Type representing a TTCN-3 integer type - */ - @Override - public OctetstringValue getOctetstring() { - return (OctetstringValue)_rb.getTciCDRequired().getOctetstring().newInstance(); - } - - @Override - public IntegerValue getBigInteger(BigInteger bigInt) { - return (IntegerValue)_rb.getTciCDRequired().getInteger().newInstance(); - } - - @Override - public Value getUnionValue(Type decodingHypothesis, String variantName) { - // TODO Auto-generated method stub - throw new RuntimeException("Not implemented for TTWB"); - } - - @Override - public Type getTypeForName(String type) { - return _rb.getTciCDRequired().getTypeForName(type); - } + /** + * RuntimeBehavior instance reference + */ + private RB _rb; + /** + * Specialized ctor + * @param rb TTCN-3 runtime reference + */ + public TciCDWrapper(final RB rb) { + _rb = rb; + } + + @Override + public IntegerValue setInteger(Integer value) { + IntegerValue iv = (IntegerValue)_rb.getTciCDRequired().getInteger().newInstance(); + iv.setInt(value); + return iv; + } + + @Override + public IntegerValue setInteger(BigInteger value) { + IntegerValue iv = (IntegerValue)_rb.getTciCDRequired().getInteger().newInstance(); + iv.setBigInt(value); + return iv; + } + + @Override + public void setInteger(BigInteger value, IntegerValue setInt) { + setInt.setBigInt(value); + } + + /** Constructs and returns a basic TTCN-3 integer type + * + * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getInteger + * @return An instance of Type representing a TTCN-3 integer type + */ +// @Override +// public IntegerValue getInteger() { +// return (IntegerValue)_rb.getTciCDRequired().getInteger().newInstance(); +// } +// + @Override + public int getInteger(IntegerValue iv) { + return iv.getInt(); + } + + @Override + public long getBigInteger(IntegerValue iv) { + return iv.getBigInt().longValue(); + } + + /** Constructs and returns a basic TTCN-3 float type + * + * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.3 getFloat + * @return An instance of Type representing a TTCN-3 float type + */ + @Override + public FloatValue getFloat() { + return (FloatValue)_rb.getTciCDRequired().getFloat().newInstance(); + } + + /** Constructs and returns a basic TTCN-3 octet string type + * + * See ETSI ES 201 873-6 V4.2.1 - 7.3.2.1.2 getOctetstring + * @return An instance of Type representing a TTCN-3 octet string type + */ + @Override + public OctetstringValue getOctetstring() { + return (OctetstringValue)_rb.getTciCDRequired().getOctetstring().newInstance(); + } + + /** Constructs and returns a basic TTCN-3 string type + * + * @return An instance of Type representing a TTCN-3 string type + */ + @Override + public CharstringValue getCharstringValue() { + return (CharstringValue)_rb.getTciCDRequired().getCharstring().newInstance(); + } + + @Override + public Value getUnionValue(Type decodingHypothesis, String variantName) { + // TODO Auto-generated method stub + throw new RuntimeException("Not implemented for TTWB"); + } + + @Override + public Type getTypeForName(String type) { + return _rb.getTciCDRequired().getTypeForName(type); + } + + @Override + public BooleanValue getBoolean() { + return (BooleanValue)_rb.getTciCDRequired().getBoolean().newInstance(); + } + + @Override + public RecordValue getRecordValue(String typeName) { + return (RecordValue) _rb.getTciCDRequired().getTypeForName(typeName); + } + + @Override + public RecordOfValue getRecordOfValue(String typeName) { + return (RecordOfValue) _rb.getTciCDRequired().getTypeForName(typeName); + } + + @Override + public EnumeratedValue getEnumValue(String typeName) { + return (EnumeratedValue) _rb.getTciCDRequired().getTypeForName(typeName); + } + } // End of class TciCDWrapper -- GitLab