diff --git a/build.xml b/build.xml index 9281cdb44..53fbcc6fa 100644 --- a/build.xml +++ b/build.xml @@ -904,7 +904,7 @@ bundle-plugin-icqaccregwizz,bundle-plugin-jabberaccregwizz, bundle-plugin-msnaccregwizz,bundle-plugin-sipaccregwizz, bundle-plugin-yahooaccregwizz,bundle-plugin-aimaccregwizz, - bundle-httputil,bundle-plugin-spellcheck, + bundle-commons-codec,bundle-httputil,bundle-plugin-spellcheck, bundle-version,bundle-version-impl,bundle-shutdown-timeout, bundle-growlnotification,bundle-swingnotification,bundle-galagonotification, bundle-sparkle, bundle-plugin-branding, @@ -918,7 +918,7 @@ bundle-jfontchooserlib,bundle-update,bundle-plugin-update, bundle-plugin-simpleaccreg,bundle-plugin-generalconfig, bundle-plugin-googletalkaccregwizz,bundle-argdelegation-service, - bundle-argdelegation,bundle-zrtp4j,bundle-json, + bundle-argdelegation,bundle-zrtp4j,bundle-sdes4j,bundle-json, bundle-filehistory,bundle-metahistory,bundle-metahistory-slick, bundle-plugin-facebookaccregwizz,bundle-plugin-ippiaccregwizz, bundle-bouncycastle,bundle-plugin-otr,bundle-plugin-iptelaccregwizz, @@ -2019,6 +2019,18 @@ javax.swing.event, javax.swing.border"/> + + + + + + + + + + + @@ -2029,7 +2041,6 @@ javax.swing.event, javax.swing.border"/> - @@ -2325,6 +2336,18 @@ javax.swing.event, javax.swing.border"/> + + + + + + + + + + + + diff --git a/ide/nbproject/project.xml b/ide/nbproject/project.xml index 8b252d0a3..22d46abb9 100644 --- a/ide/nbproject/project.xml +++ b/ide/nbproject/project.xml @@ -122,7 +122,7 @@ src - lib/felix.jar:lib/jdic-all.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/aclibico-2.1.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/concurrent.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/httpclient-4.1.1.jar:lib/installer-exclude/httpcore-4.1.jar:lib/installer-exclude/httpmime-4.1.1.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jcalendar-1.3.2.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jdom.jar:lib/installer-exclude/jfontchooser-1.0.5.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmf.jar:lib/installer-exclude/jml-1.0b5.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-20090723.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libphonenumber-2.4.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/rome-0.9.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/transparency.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/ymsg_network_v0_67.jar:lib/installer-exclude/zrtp4j-light.jar:lib/os-specific/linux/installer-exclude/jmf.jar:lib/os-specific/linux/jdic_stub.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/jdic_stub.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar:lib/os-specific/mac/installer-exclude/jmf.jar:lib/os-specific/solaris/jdic_stub.jar:lib/os-specific/solaris/installer-exclude/jmf.jar:lib/os-specific/windows/jdic_stub.jar:lib/os-specific/windows/installer-exclude/jmf.jar:lib/os-specific/windows/installer-exclude/jna-platform-win32.jar:lib/os-specific/windows/installer-exclude/sound.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/unix-0.5.jar + lib/felix.jar:lib/jdic-all.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/aclibico-2.1.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/concurrent.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/httpclient-4.1.1.jar:lib/installer-exclude/httpcore-4.1.jar:lib/installer-exclude/httpmime-4.1.1.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jcalendar-1.3.2.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jdom.jar:lib/installer-exclude/jfontchooser-1.0.5.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmf.jar:lib/installer-exclude/jml-1.0b5.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-20090723.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libphonenumber-2.4.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/rome-0.9.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/transparency.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/ymsg_network_v0_67.jar:lib/installer-exclude/zrtp4j-light.jar:lib/os-specific/linux/installer-exclude/jmf.jar:lib/os-specific/linux/jdic_stub.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/jdic_stub.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar:lib/os-specific/mac/installer-exclude/jmf.jar:lib/os-specific/solaris/jdic_stub.jar:lib/os-specific/solaris/installer-exclude/jmf.jar:lib/os-specific/windows/jdic_stub.jar:lib/os-specific/windows/installer-exclude/jmf.jar:lib/os-specific/windows/installer-exclude/jna-platform-win32.jar:lib/os-specific/windows/installer-exclude/sound.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/sdes4j.jar classes 1.5 diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index 86b4a84cb..2d63bdae7 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -39,6 +39,7 @@ felix.auto.start.30= \ reference:file:sc-bundles/fileaccess.jar felix.auto.start.35= \ + reference:file:sc-bundles/commons-codec.jar \ reference:file:sc-bundles/httputil.jar felix.auto.start.40= \ @@ -73,6 +74,7 @@ felix.auto.start.49= \ reference:file:sc-bundles/provisioning.jar \ reference:file:sc-bundles/bouncycastle.jar \ reference:file:sc-bundles/zrtp4j.jar \ + reference:file:sc-bundles/sdes4j.jar \ reference:file:sc-bundles/protocol.jar \ reference:file:sc-bundles/protocol-media.jar \ reference:file:sc-bundles/hid.jar \ diff --git a/lib/installer-exclude/sdes4j.jar b/lib/installer-exclude/sdes4j.jar new file mode 100644 index 000000000..35009d446 Binary files /dev/null and b/lib/installer-exclude/sdes4j.jar differ diff --git a/src/net/java/sip/communicator/impl/neomedia/AudioMediaStreamImpl.java b/src/net/java/sip/communicator/impl/neomedia/AudioMediaStreamImpl.java index b5ce23815..8d46de88a 100644 --- a/src/net/java/sip/communicator/impl/neomedia/AudioMediaStreamImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/AudioMediaStreamImpl.java @@ -92,14 +92,14 @@ public class AudioMediaStreamImpl * @param device the MediaDevice the new instance is to use for * both capture and playback of audio exchanged via the specified * StreamConnector - * @param zrtpControl a control which is already created, used to control - * the zrtp operations. + * @param srtpControl a control which is already created, used to control + * the srtp operations. */ public AudioMediaStreamImpl(StreamConnector connector, MediaDevice device, - ZrtpControlImpl zrtpControl) + SrtpControl srtpControl) { - super(connector, device, zrtpControl); + super(connector, device, srtpControl); if(logger.isTraceEnabled()) logger.trace("Created Audio Stream with hashCode " + hashCode()); diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java b/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java index c08844238..aa1c248e7 100644 --- a/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/MediaServiceImpl.java @@ -193,8 +193,8 @@ public MediaStream createMediaStream( * @param device the MediaDevice that the new MediaStream * instance is to use for both capture and playback of media exchanged via * the specified connector - * @param zrtpControl a control which is already created, used to control - * the zrtp operations. + * @param srtpControl a control which is already created, used to control + * the srtp operations. * * @return a new MediaStream instance * @see MediaService#createMediaStream(StreamConnector, MediaDevice) @@ -202,16 +202,14 @@ public MediaStream createMediaStream( public MediaStream createMediaStream( StreamConnector connector, MediaDevice device, - SrtpControl zrtpControl) + SrtpControl srtpControl) { switch (device.getMediaType()) { case AUDIO: - return new AudioMediaStreamImpl(connector, device, - (ZrtpControlImpl)zrtpControl); + return new AudioMediaStreamImpl(connector, device, srtpControl); case VIDEO: - return new VideoMediaStreamImpl(connector, device, - (ZrtpControlImpl)zrtpControl); + return new VideoMediaStreamImpl(connector, device, srtpControl); default: return null; } @@ -569,11 +567,21 @@ void stop() * * @return ZrtpControl instance. */ - public SrtpControl createZrtpControl() + public ZrtpControl createZrtpControl() { return new ZrtpControlImpl(); } + /** + * Creates SDesControl used to control all SDes options. + * + * @return SDesControl instance. + */ + public SDesControl createSDesControl() + { + return new SDesControlImpl(); + } + /** * Returns the control that handles current playback levels. * diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java b/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java index 429b3dfdc..af7a864d1 100644 --- a/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java @@ -198,7 +198,7 @@ else if (MediaDeviceSession.SSRC_LIST.equals(propertyName)) /** * The current ZrtpControl. */ - private final ZrtpControlImpl zrtpControl; + private final SrtpControl zrtpControl; /** * Needed when restarting zrtp control. @@ -236,12 +236,12 @@ else if (MediaDeviceSession.SSRC_LIST.equals(propertyName)) * * @param device the MediaDevice the new instance is to use for * both capture and playback of media - * @param zrtpControl an existing control instance to control the ZRTP + * @param srtpControl an existing control instance to control the SRTP * operations */ - public MediaStreamImpl(MediaDevice device, ZrtpControlImpl zrtpControl) + public MediaStreamImpl(MediaDevice device, SrtpControl srtpControl) { - this(null, device, zrtpControl); + this(null, device, srtpControl); } /** @@ -263,7 +263,7 @@ public MediaStreamImpl(MediaDevice device, ZrtpControlImpl zrtpControl) public MediaStreamImpl( StreamConnector connector, MediaDevice device, - ZrtpControlImpl zrtpControl) + SrtpControl zrtpControl) { /* * XXX Set the device early in order to make sure that it is of the @@ -352,7 +352,7 @@ private TransformEngineChain createTransformEngineChain() engineChain.add(dtmfEngine); // ZRTP - engineChain.add(zrtpControl.getZrtpEngine()); + engineChain.add(zrtpControl.getTransformEngine()); // RTCP Statistics if(statisticsEngine == null) @@ -646,10 +646,11 @@ else if (dataSource instanceof PullDataSource) // If a ZRTP engine is available then set the SSRC of this // stream // currently ZRTP supports only one SSRC per engine - ZRTPTransformEngine engine = zrtpControl.getZrtpEngine(); + TransformEngine engine = zrtpControl.getTransformEngine(); - if (engine != null) - engine.setOwnSSRC(sendStream.getSSRC()); + if (engine != null && engine instanceof ZRTPTransformEngine) + ((ZRTPTransformEngine)engine) + .setOwnSSRC(sendStream.getSSRC()); } catch (IOException ioe) { diff --git a/src/net/java/sip/communicator/impl/neomedia/SDesControlImpl.java b/src/net/java/sip/communicator/impl/neomedia/SDesControlImpl.java new file mode 100644 index 000000000..e105f7a84 --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/SDesControlImpl.java @@ -0,0 +1,130 @@ +package net.java.sip.communicator.impl.neomedia; + +import ch.imvs.sdes4j.srtp.*; + +import net.java.sip.communicator.impl.neomedia.transform.*; +import net.java.sip.communicator.impl.neomedia.transform.sdes.*; +import net.java.sip.communicator.service.neomedia.*; +import net.java.sip.communicator.service.neomedia.event.*; + +public class SDesControlImpl + implements SDesControl +{ + private String[] supportedCryptoSuites = new String[] + { + SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_80, + //SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_32, + //SrtpCryptoSuite.F8_128_HMAC_SHA1_80 + }; + private SrtpSDesFactory sdesFactory = new SrtpSDesFactory(); + private SrtpCryptoAttribute[] attributes; + private SDesTransformEngine engine; + private SrtpCryptoAttribute selectedInAttribute; + private SrtpCryptoAttribute selectedOutAttribute; + + public SDesControlImpl() + { + } + + public void cleanup() + { + } + + public void setZrtpListener(SrtpListener zrtpListener) + { + } + + public SrtpListener getSrtpListener() + { + return null; + } + + public boolean getSecureCommunicationStatus() + { + return engine != null; + } + + public void setSASVerification(boolean verified) + { + } + + public void start(boolean masterSession) + { + } + + public void setMultistream(byte[] multiStreamData) + { + } + + public TransformEngine getTransformEngine() + { + if(engine == null) + engine = new SDesTransformEngine(this); + return engine; + } + + public String[] getInitiatorCryptoAttributes() + { + attributes = new SrtpCryptoAttribute[supportedCryptoSuites.length]; + for (int i = 0; i < attributes.length; i++) + { + attributes[i] = + sdesFactory.createCryptoAttribute(i + 1, + supportedCryptoSuites[i]); + } + String[] result = new String[attributes.length]; + for(int i = 0; i < attributes.length; i++) + result[i] = attributes[i].encode(); + return result; + } + + public String responderSelectAttribute(String[] peerAttributes) + { + for (String suite : supportedCryptoSuites) + { + for (String ea : peerAttributes) + { + SrtpCryptoAttribute peerCA = SrtpCryptoAttribute.create(ea); + if (suite.equals(peerCA.getCryptoSuite().encode())) + { + selectedInAttribute = peerCA; + selectedOutAttribute = + sdesFactory.createCryptoAttribute(1, suite); + return selectedOutAttribute.encode(); + } + } + } + return null; + } + + public void initiatorSelectAttribute(String[] peerAttributes) + { + for (SrtpCryptoAttribute localCA : attributes) + { + for (String ea : peerAttributes) + { + SrtpCryptoAttribute peerCA = SrtpCryptoAttribute.create(ea); + if (localCA.getCryptoSuite().equals(peerCA.getCryptoSuite())) + { + selectedInAttribute = peerCA; + selectedOutAttribute = localCA; + return; + } + } + } + } + + public SrtpCryptoAttribute getInAttribute() + { + return selectedInAttribute; + } + + public SrtpCryptoAttribute getOutAttribute() + { + return selectedOutAttribute; + } + + public void setConnector(AbstractRTPConnector newValue) + { + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java b/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java index 12c26d141..a6030a362 100644 --- a/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/VideoMediaStreamImpl.java @@ -259,13 +259,13 @@ public int compare(FormatInfo info0, FormatInfo info1) * @param device the MediaDevice the new instance is to use for * both capture and playback of video exchanged via the specified * StreamConnector - * @param zrtpControl a control which is already created, used to control - * the zrtp operations. + * @param srtpControl a control which is already created, used to control + * the srtp operations. */ public VideoMediaStreamImpl(StreamConnector connector, MediaDevice device, - ZrtpControlImpl zrtpControl) + SrtpControl srtpControl) { - super(connector, device, zrtpControl); + super(connector, device, srtpControl); if(logger.isTraceEnabled()) logger.trace("Created Video Stream with hashCode " + hashCode()); diff --git a/src/net/java/sip/communicator/impl/neomedia/ZrtpControlImpl.java b/src/net/java/sip/communicator/impl/neomedia/ZrtpControlImpl.java index ff520986e..bafe48b88 100644 --- a/src/net/java/sip/communicator/impl/neomedia/ZrtpControlImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/ZrtpControlImpl.java @@ -20,7 +20,7 @@ * @author Damian Minkov */ public class ZrtpControlImpl - implements SrtpControl + implements ZrtpControl { /** * The listener interested in security events about zrtp. @@ -112,7 +112,7 @@ public boolean getSecureCommunicationStatus() */ public void setSASVerification(boolean verified) { - ZRTPTransformEngine engine = getZrtpEngine(); + ZRTPTransformEngine engine = getTransformEngine(); if (verified) engine.SASVerified(); @@ -124,7 +124,7 @@ public void setSASVerification(boolean verified) * Returns the zrtp engine currently used by this stream. * @return the zrtp engine */ - public ZRTPTransformEngine getZrtpEngine() + public ZRTPTransformEngine getTransformEngine() { if(zrtpEngine == null) { @@ -151,7 +151,7 @@ public void start(boolean masterSession) boolean zrtpAutoStart = false; // ZRTP engine initialization - ZRTPTransformEngine engine = getZrtpEngine(); + ZRTPTransformEngine engine = getTransformEngine(); // Decide if this will become the ZRTP Master session: // - Statement: audio media session will be started before video @@ -209,7 +209,7 @@ public void start(boolean masterSession) */ public void setMultistream(byte[] multiStreamData) { - ZRTPTransformEngine engine = getZrtpEngine(); + ZRTPTransformEngine engine = getTransformEngine(); engine.setMultiStrParams(multiStreamData); engine.setEnableZrtp(true); @@ -222,7 +222,7 @@ public void setMultistream(byte[] multiStreamData) */ public String getHelloHash() { - return getZrtpEngine().getHelloHash(); + return getTransformEngine().getHelloHash(); } /** @@ -235,7 +235,7 @@ public String getHelloHash() */ public String[] getHelloHashSep() { - return getZrtpEngine().getHelloHashSep(); + return getTransformEngine().getHelloHashSep(); } /** diff --git a/src/net/java/sip/communicator/impl/neomedia/neomedia.manifest.mf b/src/net/java/sip/communicator/impl/neomedia/neomedia.manifest.mf index 400221eff..2a9610ae2 100644 --- a/src/net/java/sip/communicator/impl/neomedia/neomedia.manifest.mf +++ b/src/net/java/sip/communicator/impl/neomedia/neomedia.manifest.mf @@ -43,7 +43,9 @@ Import-Package: org.bouncycastle.crypto, gnu.java.zrtp.packets, gnu.java.zrtp.utils, gnu.java.zrtp.zidfile, - apple.awt + apple.awt, + ch.imvs.sdes4j, + ch.imvs.sdes4j.srtp Export-Package: net.java.sip.communicator.service.audionotifier, net.java.sip.communicator.service.neomedia, net.java.sip.communicator.service.neomedia.control, diff --git a/src/net/java/sip/communicator/impl/neomedia/transform/sdes/SDesTransformEngine.java b/src/net/java/sip/communicator/impl/neomedia/transform/sdes/SDesTransformEngine.java new file mode 100644 index 000000000..3e352053e --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/transform/sdes/SDesTransformEngine.java @@ -0,0 +1,142 @@ +package net.java.sip.communicator.impl.neomedia.transform.sdes; + +import ch.imvs.sdes4j.srtp.*; + +import net.java.sip.communicator.impl.neomedia.*; +import net.java.sip.communicator.impl.neomedia.transform.*; +import net.java.sip.communicator.impl.neomedia.transform.srtp.*; + +public class SDesTransformEngine + implements TransformEngine, PacketTransformer +{ + private SRTPCryptoContext inContext; + private SRTPCryptoContext outContext; + private SrtpCryptoAttribute inAttribute; + private SrtpCryptoAttribute outAttribute; + + public SDesTransformEngine(SDesControlImpl sDesControl) + { + inAttribute = sDesControl.getInAttribute(); + outAttribute = sDesControl.getOutAttribute(); + } + + private long getKdr(SrtpCryptoAttribute attribute) + { + if(attribute.getSessionParams() != null) + { + for (SrtpSessionParam param : attribute.getSessionParams()) + { + if (param instanceof KdrSessionParam) + return ((KdrSessionParam) param).getKeyDerivationRateExpanded(); + } + } + return 0; + } + + private byte[] getKey(SrtpCryptoAttribute attribute) + { + int length = attribute.getCryptoSuite().getEncKeyLength()/8; + byte[] key = new byte[length]; + System.arraycopy(attribute.getKeyParams()[0].getKey(), 0, key, 0, length); + return key; + } + + private byte[] getSalt(SrtpCryptoAttribute attribute) + { + int keyLength = attribute.getCryptoSuite().getEncKeyLength()/8; + int saltLength = attribute.getCryptoSuite().getSaltKeyLength()/8; + byte[] salt = new byte[keyLength]; + System.arraycopy(attribute.getKeyParams()[0].getKey(), keyLength, salt, 0, + saltLength); + return salt; + } + + public PacketTransformer getRTPTransformer() + { + return this; + } + + public PacketTransformer getRTCPTransformer() + { + return null; + } + + private SRTPCryptoContext createContext(long ssrc, SrtpCryptoAttribute attribute) + { + int encType; + SrtpCryptoSuite cs = attribute.getCryptoSuite(); + switch(cs.getEncryptionAlgorithm()) + { + case SrtpCryptoSuite.ENCRYPTION_AES128_CM: + encType = SRTPPolicy.AESCM_ENCRYPTION; + break; + case SrtpCryptoSuite.ENCRYPTION_AES128_F8: + encType = SRTPPolicy.AESF8_ENCRYPTION; + break; + default: + throw new IllegalArgumentException("Unsupported cipher"); + } + int authType; + switch(cs.getHashAlgorithm()) + { + case SrtpCryptoSuite.HASH_HMAC_SHA1: + authType = SRTPPolicy.HMACSHA1_AUTHENTICATION; + break; + default: + throw new IllegalArgumentException("Unsupported hash"); + } + SRTPPolicy policy = new SRTPPolicy( + encType, cs.getEncKeyLength()/8, + authType, cs.getSrtpAuthKeyLength()/8, cs.getSrtpAuthTagLength()/8, + cs.getSaltKeyLength()/8 + ); + return new SRTPCryptoContext( + ssrc, 0, getKdr(attribute), + getKey(attribute), + getSalt(attribute), + policy + ); + } + + public RawPacket transform(RawPacket pkt) + { + if (outContext == null) + { + outContext = createContext(pkt.getSSRC(), outAttribute); + outContext.deriveSrtpKeys(0); + } + + outContext.transformPacket(pkt); + return pkt; + } + + public RawPacket reverseTransform(RawPacket pkt) + { + long ssrc = pkt.getSSRC(); + int seqNum = pkt.getSequenceNumber(); + + boolean isNewContext = false; + if (inContext == null) + { + inContext = createContext(ssrc, inAttribute); + inContext.deriveSrtpKeys(seqNum); + isNewContext = true; + } + else if(ssrc != inContext.getSSRC()) + { + // invalid packet, don't even try to decode + return null; + } + + boolean validPacket = inContext.reverseTransformPacket(pkt); + if(!validPacket && isNewContext) + inContext = null; + + if (!validPacket) + { + return null; + } + + return pkt; + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/transform/srtp/SRTPCryptoContext.java b/src/net/java/sip/communicator/impl/neomedia/transform/srtp/SRTPCryptoContext.java index df6f5dcc3..908ece43f 100644 --- a/src/net/java/sip/communicator/impl/neomedia/transform/srtp/SRTPCryptoContext.java +++ b/src/net/java/sip/communicator/impl/neomedia/transform/srtp/SRTPCryptoContext.java @@ -53,7 +53,7 @@ * Cryptographic related parameters, i.e. encryption mode / authentication mode, * master encryption key and master salt key are determined outside the scope * of SRTP implementation. They can be assigned manually, or can be assigned - * automatically using some key management protocol, such as MIKEY (RFC3880) or + * automatically using some key management protocol, such as MIKEY (RFC3830) or * Phil Zimmermann's ZRTP protocol (draft-zimmermann-avt-zrtp-01). * * @author Bing SU (nova.su@gmail.com) diff --git a/src/net/java/sip/communicator/impl/neomedia/transform/zrtp/SecurityEventManager.java b/src/net/java/sip/communicator/impl/neomedia/transform/zrtp/SecurityEventManager.java index db332e133..38b19b26c 100644 --- a/src/net/java/sip/communicator/impl/neomedia/transform/zrtp/SecurityEventManager.java +++ b/src/net/java/sip/communicator/impl/neomedia/transform/zrtp/SecurityEventManager.java @@ -212,7 +212,7 @@ public void showMessage(ZrtpCodes.MessageSeverity sev, { securityListener.securityTurnedOn( sessionType, cipher, sas, isSasVerified, - zrtpControl.getZrtpEngine().getMultiStrParams()); + zrtpControl.getTransformEngine().getMultiStrParams()); } else { diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java index 523d3db1e..2293e41fe 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java @@ -344,14 +344,14 @@ public void processOffer(List offer) if(getPeer().getCall().isSipZrtpAttribute()) { SrtpControl control = getZrtpControls().get(mediaType); - if(control == null) + if(control == null || !(control instanceof ZrtpControl)) { control = JabberActivator.getMediaService() .createZrtpControl(); getZrtpControls().put(mediaType, control); } - String helloHash[] = control.getHelloHashSep(); + String helloHash[] = ((ZrtpControl)control).getHelloHashSep(); if(helloHash != null && helloHash[1].length() > 0) { @@ -552,14 +552,14 @@ private ContentPacketExtension createContent(MediaDevice dev) { SrtpControl control = getZrtpControls().get(dev.getMediaType()); - if(control == null) + if(control == null || !(control instanceof ZrtpControl)) { control = JabberActivator.getMediaService().createZrtpControl(); getZrtpControls().put(dev.getMediaType(), control); } - String helloHash[] = control.getHelloHashSep(); + String helloHash[] = ((ZrtpControl)control).getHelloHashSep(); if(helloHash != null && helloHash[1].length() > 0) { @@ -690,14 +690,15 @@ public List createContentList() if(getPeer().getCall().isSipZrtpAttribute()) { SrtpControl control = getZrtpControls().get(mediaType); - if(control == null) + if(control == null || !(control instanceof ZrtpControl)) { control = JabberActivator.getMediaService() .createZrtpControl(); getZrtpControls().put(mediaType, control); } - String helloHash[] = control.getHelloHashSep(); + String helloHash[] = + ((ZrtpControl) control).getHelloHashSep(); if(helloHash != null && helloHash[1].length() > 0) { diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java index f43338012..6c8e75fcc 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java @@ -191,12 +191,13 @@ private Vector createMediaDescriptions() { MediaDescription md = createMediaDescription( - dev.getSupportedFormats( - sendQualityPreset, - receiveQualityPreset), - getTransportManager().getStreamConnector(mediaType), - direction, - dev.getSupportedExtensions()); + true, //TODO base on settings + dev.getSupportedFormats( + sendQualityPreset, + receiveQualityPreset), + getTransportManager().getStreamConnector(mediaType), + direction, + dev.getSupportedExtensions()); try { @@ -215,7 +216,8 @@ private Vector createMediaDescriptions() // do nothing in case of error. } - updateMediaDescriptionForZrtp(mediaType, md); + //updateMediaDescriptionForZrtp(mediaType, md); //TODO: base on setting + updateMediaDescriptionForSDes(mediaType, md, null); mediaDescs.add(md); } @@ -476,11 +478,6 @@ private Vector createMediaDescriptionsForAnswer( StreamConnector connector = getTransportManager().getStreamConnector(mediaType); - // create the corresponding stream... - MediaFormat fmt = findMediaFormat(remoteFormats, - mutuallySupportedFormats.get(0)); - initStream(connector, dev, fmt, target, direction, rtpExtensions); - // check for options from remote party and set them locally if(mediaType.equals(MediaType.VIDEO)) { @@ -527,10 +524,16 @@ private Vector createMediaDescriptionsForAnswer( } } - MediaDescription md = createMediaDescription( + MediaDescription md = createMediaDescription(true, //TODO base on settings mutuallySupportedFormats, connector, direction, rtpExtensions); - updateMediaDescriptionForZrtp(mediaType, md); + //updateMediaDescriptionForZrtp(mediaType, md); //TODO base on setting + updateMediaDescriptionForSDes(mediaType, md, mediaDescription); + + // create the corresponding stream... + MediaFormat fmt = findMediaFormat(remoteFormats, + mutuallySupportedFormats.get(0)); + initStream(connector, dev, fmt, target, direction, rtpExtensions); // create the answer description answerDescriptions.add(md); @@ -559,26 +562,94 @@ private void updateMediaDescriptionForZrtp( { try { - SrtpControl control - = getZrtpControls().get(mediaType); - if(control == null) + SrtpControl scontrol = getZrtpControls().get(mediaType); + if(scontrol == null || !(scontrol instanceof ZrtpControl)) { - control = SipActivator.getMediaService() + scontrol = SipActivator.getMediaService() .createZrtpControl(); - getZrtpControls().put(mediaType, control); + getZrtpControls().put(mediaType, scontrol); } + ZrtpControl zcontrol = (ZrtpControl) scontrol; - String helloHash = control.getHelloHash(); + String helloHash = zcontrol.getHelloHash(); if(helloHash != null && helloHash.length() > 0) md.setAttribute("zrtp-hash", helloHash); - } catch (SdpException ex) + } + catch (SdpException ex) { logger.error("Cannot add zrtp-hash to sdp", ex); } } } + /** + * Updates the supplied description with SDES attributes if necessary. + * + * @param mediaType the media type. + * @param localMd the description to be updated. + * @param peerMd + * @throws OperationFailedException + */ + @SuppressWarnings("unchecked") //jain-sip legacy + private void updateMediaDescriptionForSDes( + MediaType mediaType, MediaDescription localMd, MediaDescription peerMd) + throws OperationFailedException + { + //if(getPeer().getCall().isSipZrtpAttribute()) //TODO: check SDES config + { + SrtpControl scontrol = getZrtpControls().get(mediaType); + if (scontrol == null || !(scontrol instanceof SDesControl)) + { + scontrol = SipActivator.getMediaService().createSDesControl(); + getZrtpControls().put(mediaType, scontrol); + } + SDesControl sdcontrol = (SDesControl) scontrol; + if (peerMd == null) + { + Vector atts = localMd.getAttributes(true); + for (String ca : sdcontrol.getInitiatorCryptoAttributes()) + { + Attribute a = SdpUtils.createAttribute("crypto", ca); + atts.add(a); + } + } + else + { + Vector atts = peerMd.getAttributes(true); + List peerAttributes = new LinkedList(); + for (Attribute a : atts) + { + try + { + if (a.getName().equals("crypto")) + { + peerAttributes.add(a.getValue()); + } + } + catch (SdpParseException e) + { + logger.error("received an uparsable sdp attribute", e); + } + } + if (peerAttributes.size() > 0) + { + String localAttr = + sdcontrol.responderSelectAttribute(peerAttributes + .toArray(new String[peerAttributes.size()])); + try + { + localMd.setAttribute("crypto", localAttr); + } + catch (SdpException e) + { + logger.error("unable to add crypto to answer", e); + } + } + } + } + } + /** * Handles the specified answer by creating and initializing the * corresponding MediaStreams. @@ -715,6 +786,32 @@ private synchronized void processAnswer(SessionDescription answer) supportQualityControls = SdpUtils.containsAttribute(mediaDescription, "imageattr"); } + + // select the crypto key the peer has chosen from our proposal + SrtpControl scontrol = getZrtpControls().get(mediaType); + if(scontrol != null && scontrol instanceof SDesControl) + { + List peerAttributes = new LinkedList(); + @SuppressWarnings("unchecked") + Vector attrs = mediaDescription.getAttributes(true); + for (Attribute a : attrs) + { + try + { + if (a.getName().equals("crypto")) + { + peerAttributes.add(a.getValue()); + } + } + catch (SdpParseException e) + { + logger.error("received an uparsable sdp attribute", e); + } + } + ((SDesControl) scontrol) + .initiatorSelectAttribute(peerAttributes + .toArray(new String[peerAttributes.size()])); + } } } @@ -735,6 +832,7 @@ private String getUserName() * taking account the local streaming preference for the corresponding * media type. * + * @param secure when true, the profile is RTP/SAVP instead of RTP/AVP * @param formats the list of MediaFormats that we'd like to * advertise. * @param connector the StreamConnector that we will be using @@ -751,13 +849,14 @@ private String getUserName() * MediaDescription fails for some reason. */ private MediaDescription createMediaDescription( + boolean secure, List formats, StreamConnector connector, MediaDirection direction, List extensions ) throws OperationFailedException { - return SdpUtils.createMediaDescription(formats, connector, + return SdpUtils.createMediaDescription(secure, formats, connector, direction, extensions, getDynamicPayloadTypes(), getRtpExtensionsRegistry()); } diff --git a/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java b/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java index 216417af0..a3f8c775c 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java @@ -1284,6 +1284,7 @@ public static URL getCallInfoURL(SessionDescription sessDesc) * description is determined via from the type of the first * MediaFormat in the formats list. * + * @param secure when true, the profile is RTP/SAVP instead of RTP/AVP * @param formats the list of formats that should be advertised in the newly * created MediaDescription. * @param connector the socket couple that will be used for the media stream @@ -1306,6 +1307,7 @@ public static URL getCallInfoURL(SessionDescription sessDesc) * some other reason. */ public static MediaDescription createMediaDescription( + boolean secure, List formats, StreamConnector connector, MediaDirection direction, @@ -1435,7 +1437,8 @@ public static MediaDescription createMediaDescription( { mediaDesc = sdpFactory.createMediaDescription(mediaType.toString(), connector.getDataSocket().getLocalPort(), 1, - SdpConstants.RTP_AVP, payloadTypesArray); + secure ? "RTP/SAVP" : SdpConstants.RTP_AVP, + payloadTypesArray); // add all the attributes we have created above mediaDesc.setAttributes(mediaAttributes); diff --git a/src/net/java/sip/communicator/service/neomedia/MediaService.java b/src/net/java/sip/communicator/service/neomedia/MediaService.java index b910af0c7..76e657e2b 100644 --- a/src/net/java/sip/communicator/service/neomedia/MediaService.java +++ b/src/net/java/sip/communicator/service/neomedia/MediaService.java @@ -135,7 +135,14 @@ public MediaStream createMediaStream(StreamConnector connector, * * @return ZrtpControl instance. */ - public SrtpControl createZrtpControl(); + public ZrtpControl createZrtpControl(); + + /** + * Creates SDesControl used to control all SDes options. + * + * @return SDesControl instance. + */ + public SDesControl createSDesControl(); /** * Returns the control that handles current playback levels. diff --git a/src/net/java/sip/communicator/service/neomedia/SDesControl.java b/src/net/java/sip/communicator/service/neomedia/SDesControl.java new file mode 100644 index 000000000..6f7e28554 --- /dev/null +++ b/src/net/java/sip/communicator/service/neomedia/SDesControl.java @@ -0,0 +1,13 @@ +package net.java.sip.communicator.service.neomedia; + +import ch.imvs.sdes4j.srtp.SrtpCryptoAttribute; + +public interface SDesControl + extends SrtpControl +{ + public String[] getInitiatorCryptoAttributes(); + public String responderSelectAttribute(String[] peerAttributes); + public void initiatorSelectAttribute(String[] peerAttributes); + public SrtpCryptoAttribute getInAttribute(); + public SrtpCryptoAttribute getOutAttribute(); +} diff --git a/src/net/java/sip/communicator/service/neomedia/SrtpControl.java b/src/net/java/sip/communicator/service/neomedia/SrtpControl.java index 7b13c3f11..3df982b50 100644 --- a/src/net/java/sip/communicator/service/neomedia/SrtpControl.java +++ b/src/net/java/sip/communicator/service/neomedia/SrtpControl.java @@ -6,6 +6,8 @@ */ package net.java.sip.communicator.service.neomedia; +import net.java.sip.communicator.impl.neomedia.AbstractRTPConnector; +import net.java.sip.communicator.impl.neomedia.transform.TransformEngine; import net.java.sip.communicator.service.neomedia.event.*; /** @@ -68,19 +70,11 @@ public interface SrtpControl public void setMultistream(byte[] multiStreamData); /** - * Return the zrtp hello hash String. - * - * @return String the zrtp hello hash. + * Returns the transform engine currently used by this stream. + * + * @return the transofmr engine */ - public String getHelloHash(); + public TransformEngine getTransformEngine(); - /** - * Get the ZRTP Hello Hash data - separate strings. - * - * @return String array containing the version string at offset 0, the Hello - * hash value as hex-digits at offset 1. Hello hash is available - * immediately after class instantiation. Returns null - * if ZRTP is not available. - */ - public String[] getHelloHashSep(); + public void setConnector(AbstractRTPConnector newValue); } diff --git a/src/net/java/sip/communicator/service/neomedia/ZrtpControl.java b/src/net/java/sip/communicator/service/neomedia/ZrtpControl.java new file mode 100644 index 000000000..9adb75369 --- /dev/null +++ b/src/net/java/sip/communicator/service/neomedia/ZrtpControl.java @@ -0,0 +1,22 @@ +package net.java.sip.communicator.service.neomedia; + +public interface ZrtpControl + extends SrtpControl +{ + /** + * Return the zrtp hello hash String. + * + * @return String the zrtp hello hash. + */ + public String getHelloHash(); + + /** + * Get the ZRTP Hello Hash data - separate strings. + * + * @return String array containing the version string at offset 0, the Hello + * hash value as hex-digits at offset 1. Hello hash is available + * immediately after class instantiation. Returns null + * if ZRTP is not available. + */ + public String[] getHelloHashSep(); +} diff --git a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java index c1c788792..f67b6f03f 100644 --- a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java +++ b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java @@ -193,7 +193,7 @@ public abstract class CallPeerMediaHandler< /** * Holds the ZRTP controls used for the current call. */ - private Map zrtpControls = + private Map srtpControls = new Hashtable(); /** @@ -423,12 +423,12 @@ protected void closeStream(MediaType type) getTransportManager().closeStreamConnector(type); // Clear the ZRTP controls used for the associated Call. - SrtpControl zrtpCtrl = zrtpControls.get(type); + SrtpControl zrtpCtrl = srtpControls.get(type); if (zrtpCtrl != null) { zrtpCtrl.cleanup(); - zrtpControls.remove(type); + srtpControls.remove(type); } } @@ -1163,7 +1163,7 @@ public void setCsrcAudioLevelListener( */ protected Map getZrtpControls() { - return this.zrtpControls; + return this.srtpControls; } /** @@ -1206,7 +1206,7 @@ protected MediaStream initStream(StreamConnector connector, logger.trace("The media types of device and format differ."); // check whether a control already exists - SrtpControl control = zrtpControls.get(mediaType); + SrtpControl control = srtpControls.get(mediaType); MediaService mediaService = ProtocolMediaActivator.getMediaService();