/* * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. * * Distributable under LGPL license. * See terms of license at gnu.org. */ package net.java.sip.communicator.impl.media.transform.zrtp; import gnu.java.zrtp.*; import gnu.java.zrtp.zidfile.*; import org.osgi.framework.*; import net.java.sip.communicator.impl.media.*; import net.java.sip.communicator.impl.media.transform.*; import net.java.sip.communicator.impl.media.transform.srtp.*; import net.java.sip.communicator.service.fileaccess.*; import net.java.sip.communicator.util.*; import java.io.*; import java.util.EnumSet; /** * JMF extension/connector to support GNU ZRTP4J. * * ZRTP was developed by Phil Zimmermann and provides functions to negotiate * keys and other necessary data (crypto data) to set-up the Secure RTP (SRTP) * crypto context. Refer to Phil's ZRTP specification at his * <a href="http://zfoneproject.com/">Zfone project</a> site to get more * detailed information about the capabilities of ZRTP. * * <h3>Short overview of the ZRTP4J implementation</h3> * * ZRTP is a specific protocol to negotiate encryption algorithms and the * required key material. ZRTP uses a RTP session to exchange its protocol * messages. * * A complete GNU ZRTP4J implementation consists of two parts, the GNU ZRTP4J * core and specific code that binds the GNU ZRTP core to the underlying * RTP/SRTP stack and the operating system: * <ul> * <li> The GNU ZRTP core is independent of a specific RTP/SRTP stack and the * operationg system and consists of the ZRTP protocol state engine, the ZRTP * protocol messages, and the GNU ZRTP4J engine. The GNU ZRTP4J engine provides * methods to setup ZRTP message and to analyze received ZRTP messages, to * compute the crypto data required for SRTP, and to maintain the required * hashes and HMAC. </li> * <li> The second part of an implementation is specific <em>glue</em> code * the binds the GNU ZRTP core to the actual RTP/SRTP implementation and other * operating system specific services such as timers. </li> * </ul> * * The GNU ZRTP4J core uses a callback interface class (refer to ZrtpCallback) * to access RTP/SRTP or operating specific methods, for example to send data * via the RTP/SRTP stack, to access timers, provide mutex handling, and to * report events to the application. * * <h3>The ZRTPTransformEngine</h3> * * ZRTPTransformEngine implements code that is specific to the JMF * implementation. * * To perform its tasks ZRTPTransformEngine * <ul> * <li> extends specific classes to hook into the JMF RTP methods and the * RTP/SRTP send and receive queues </li> * <li> implements the ZrtpCallback interface to provide to enable data send and * receive other specific services (timer to GNU ZRTP4J </li> * <li> provides ZRTP specific methods that applications may use to control and * setup GNU ZRTP </li> * <li> can register and use an application specific callback class (refer to * ZrtpUserCallback) </li> * </ul> * * After instantiating a GNU ZRTP4J session (see below for a short example) * applications may use the ZRTP specific methods of ZRTPTransformEngine to * control and setup GNU ZRTP, for example enable or disable ZRTP processing or * getting ZRTP status information. * * GNU ZRTP4J provides a ZrtpUserCallback class that an application may extend * and register with ZRTPTransformEngine. GNU ZRTP4J and ZRTPTransformEngine use * the ZrtpUserCallback methods to report ZRTP events to the application. The * application may display this information to the user or act otherwise. * * The following figure depicts the relationships between ZRTPTransformEngine, * JMF implementation, the GNU ZRTP4J core, and an application that provides an * ZrtpUserCallback class. * * <pre> * * +---------------------------+ * | ZrtpTransformConnector | * | extends TransformConnector| * | implements RTPConnector | * +---------------------------+ * | * | uses * | * +----------------+ +-----+---------------+ * | Application | | | +----------------+ * | instantiates | uses | ZRTPTransformEngine | uses | | * | a ZRTP Session +------+ implements +------+ GNU ZRTP4J | * | and provides | | ZrtpCallback | | core | * |ZrtpUserCallback| | | | implementation | * +----------------+ +---------------------+ | (ZRtp et al) | * | | * +----------------+ * </pre> * * The following short code snippets show how an application could instantiate a * ZrtpTransformConnector, get the ZRTP4J engine and initialize it. Then the * code get a RTP manager instance and initializes it with the * ZRTPTransformConnector. Plase note: setting the target must be done with the * connector, not with the RTP manager. * * <pre> * ... * transConnector = (ZrtpTransformConnector)TransformManager * .createZRTPConnector(sa); * zrtpEngine = transConnector.getEngine(); * zrtpEngine.setUserCallback(new MyCallback()); * if (!zrtpEngine.initialize("test_t.zid")) * System.out.println("iniatlize failed"); * * // initialize the RTPManager using the ZRTP connector * * mgr = RTPManager.newInstance(); * mgr.initialize(transConnector); * * mgr.addSessionListener(this); * mgr.addReceiveStreamListener(this); * * transConnector.addTarget(target); * zrtpEngine.startZrtp(); * * ... * </pre> * * The <em>demo</em> folder contains a small example that shows how to use GNU * ZRTP4J. * * This ZRTPTransformEngine documentation shows the ZRTP specific extensions and * describes overloaded methods and a possible different behaviour. * * @author Werner Dittmann <Werner.Dittmann@t-online.de> * */ public class ZRTPTransformEngine implements TransformEngine, PacketTransformer, ZrtpCallback { /** * Very simple Timeout provider class. * * This very simple timeout provider can handle one timeout request at * one time only. A second request would overwrite the first one and would * lead to unexpected results. * * @author Werner Dittmann <Werner.Dittmann@t-online.de> */ private static class TimeoutProvider extends Thread { public TimeoutProvider(String name) { super(name); } private ZRTPTransformEngine executor; private long nextDelay = 0; private boolean newTask = false; private boolean stop = false; private final Object sync = new Object(); public synchronized void requestTimeout(long delay, ZRTPTransformEngine tt) { synchronized (sync) { executor = tt; nextDelay = delay; newTask = true; sync.notifyAll(); } } public void stopRun() { synchronized (sync) { stop = true; sync.notifyAll(); } } public void cancelRequest() { synchronized (sync) { newTask = false; sync.notifyAll(); } } public void run() { while (!stop) { synchronized (sync) { while (!newTask && !stop) { try { sync.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } long endTime = System.currentTimeMillis() + nextDelay; long currentTime = System.currentTimeMillis(); synchronized (sync) { while ((currentTime < endTime) && newTask && !stop) { try { sync.wait(endTime - currentTime); } catch (InterruptedException e) { e.printStackTrace(); } currentTime = System.currentTimeMillis(); } } if (newTask && !stop) { newTask = false; executor.handleTimeout(); } } } } private static final Logger logger = Logger.getLogger(ZRTPTransformEngine.class); /** * Each ZRTP packet has a fixed header of 12 bytes. */ protected static final int ZRTP_PACKET_HEADER = 12; /** * This is the own ZRTP connector, required to send ZRTP packets * via the DatagramSocket. * (Note: in order to further multistream support this should be * replaced with a connector array; each connector would handle * a stream) */ private TransformConnector zrtpConnector = null; /** * We need Out and In SRTPTransformer to transform RTP to SRTP and * vice versa. */ private PacketTransformer srtpOutTransformer = null; private PacketTransformer srtpInTransformer = null; /** * User callback class. */ private SecurityEventManager securityEventManager = null; /** * The ZRTP engine. */ private ZRtp zrtpEngine = null; /** * ZRTP engine enable flag (used for auto-enable at initialization) */ private boolean enableZrtp = false; /** * Client ID string initialized with the name of the ZRTP4j library */ private String clientIdString = ZrtpConstants.clientId; /** * SSRC identifier for the ZRTP packets */ private int ownSSRC = 0; /** * ZRTP packet sequence number */ private short senderZrtpSeqNo = 0; /** * The number of sent packets */ private long sendPacketCount = 0; /** * The timeout provider instance * This is used for handling the ZRTP timers */ private TimeoutProvider timeoutProvider = null; /** * The current condition of the ZRTP engine */ private boolean started = false; /** * The flag used to temporarily stop the media streaming * required by the GoClear transition */ private boolean holdFlag = false; /** * Only multi-stream session may be started as one-way communication * channels. */ private boolean multiStream = false; /** * Construct a ZRTPTransformEngine. * */ public ZRTPTransformEngine() { senderZrtpSeqNo = 1; // should be a random number } /** * Returns an instance of <tt>ZRTPCTransformer</tt>. * * @see net.java.sip.communicator.impl.media.transform. * TransformEngine#getRTCPTransformer() */ public PacketTransformer getRTCPTransformer() { return new ZRTPCTransformer(this); } /** * Returns this RTPTransformer. * * @see net.java.sip.communicator.impl.media.transform. * TransformEngine#getRTPTransformer() */ public PacketTransformer getRTPTransformer() { return this; } /** * Default engine initialization method. * Calling this for engine initialization and start it with auto-sensing. * * @param zidFilename The ZID file name * @return true if initialization fails, false if succeeds */ public synchronized boolean initialize(String zidFilename) { return initialize(zidFilename, true); } /** * Custom engine initialization method. * This allows to explicit specify if the engine starts with auto-sensing * or not. * * @param zidFilename The ZID file name * @param autoEnable Set this true to start with auto-sensing and false to * disable it. * @return true if initialization fails, false if succeeds */ public synchronized boolean initialize(String zidFilename, boolean autoEnable) { // Get a reference to the FileAccessService BundleContext bc = MediaActivator.getBundleContext(); ServiceReference faServiceReference = bc.getServiceReference( FileAccessService.class.getName()); FileAccessService faService = (FileAccessService) bc.getService(faServiceReference); File file = null; try { // Create the zid file file = faService.getPrivatePersistentFile(zidFilename); } catch (Exception e) { logger.warn("Failed to create the zid file."); if (logger.isDebugEnabled()) logger.debug("Failed to create the zid file.", e); } String zidFilePath = null; try { // Get the absolute path of the created zid file zidFilePath = file.getAbsolutePath(); } catch (SecurityException e) { if (logger.isDebugEnabled()) logger.debug( "Failed to obtain the absolute path of the zid file.", e); } ZidFile zf = ZidFile.getInstance(); if (!zf.isOpen()) { String fname; if (zidFilePath == null) { String home = System.getenv("HOME"); String baseDir = (home != null) ? ((home) + ("/.")) : "."; fname = baseDir + "GNUZRTP4J.zid"; zidFilename = fname; } else { zidFilename = zidFilePath; } if (zf.open(zidFilename) < 0) { return false; } } zrtpEngine = new ZRtp(zf.getZid(), this, clientIdString); if (timeoutProvider == null) { timeoutProvider = new TimeoutProvider("ZRTP"); timeoutProvider.setDaemon(true); timeoutProvider.start(); } enableZrtp = autoEnable; return true; } /** * Start the ZRTP stack immediately, not autosensing mode. */ public void startZrtp() { if (zrtpEngine != null) { zrtpEngine.startZrtpEngine(); started = true; } } /** * Stop ZRTP engine. */ public void stopZrtp() { if (zrtpEngine != null) { zrtpEngine.stopZrtp(); zrtpEngine = null; started = false; } } /** * Cleanup function for any remaining timers */ public void cleanup() { if (timeoutProvider != null) { timeoutProvider.stopRun(); timeoutProvider = null; } } /** * The data output stream calls this method to transform outgoing * packets. * * @see net.java.sip.communicator.impl.media.transform.PacketTransformer# * transform(net.java.sip.communicator.impl.media.transform.RawPacket) */ public RawPacket transform(RawPacket pkt) { ZrtpRawPacket zPkt = new ZrtpRawPacket(pkt); /* * Never transform outgoing ZRTP packets. */ if (zPkt.isZrtpPacket()) { return pkt; } /* * Discard the media packets if the hold flag is set * (Needed in the GoClear transition) */ /* TODO GoClear * To uncomment in order to use the GoClear feature * (uncomment also the check in write method of TransformOutputStream) */ /* if (holdFlag) return null; */ // ZRTP needs the SSRC of the sending stream. if (enableZrtp && ownSSRC == 0) { ownSSRC = zPkt.getSSRC(); } // If SRTP is active then srtpTransformer is set, use it. sendPacketCount++; if (srtpOutTransformer == null) { return pkt; } return srtpOutTransformer.transform(pkt); } /** * The input data stream calls this method to transform * incoming packets. * * @see net.java.sip.communicator.impl.media.transform.PacketTransformer# * reverseTransform( * net.java.sip.communicator.impl.media.transform.RawPacket) */ public RawPacket reverseTransform(RawPacket pkt) { ZrtpRawPacket zPkt = new ZrtpRawPacket(pkt); /* * Check if incoming packt is a ZRTP packet, if no treat * it as normal RTP packet and handle it accordingly. */ if (!zPkt.isZrtpPacket()) { if (!started && enableZrtp && (multiStream || (sendPacketCount >= 1))) { startZrtp(); } if (srtpInTransformer == null) { return pkt; } pkt = srtpInTransformer.reverseTransform(pkt); // if packet was valid (i.e. not null) and ZRTP engine started and // not yet in secure state - emulate a Conf2Ack packet. See ZRTP // specification chap. 5.6 if (pkt != null && zrtpEngine != null && !zrtpEngine.inState(ZrtpStateClass.ZrtpStates.SecureState)) { zrtpEngine.conf2AckSecure(); } return pkt; } /* * If ZRTP is enabled process it. In any case return null * because ZRTP packets never reach the application. */ if (enableZrtp) { if (!zPkt.checkCrc()) { securityEventManager.showMessage(ZrtpCodes.MessageSeverity.Warning, EnumSet.of(ZrtpCodes.WarningCodes.WarningCRCmismatch)); return null; } // Check if it is really a ZRTP packet, if not don't process it if (!zPkt.hasMagic() || zrtpEngine == null) { return null; } byte[] extHeader = zPkt.getMessagePart(); zrtpEngine.processZrtpMessage(extHeader); } return null; } /** * The callback method required by the ZRTP implementation. * First allocate space to hold the complete ZRTP packet, copy * the message part in its place, the initalize the header, counter, * SSRC and crc. * * @param data The ZRTP packet data * @return true if sending succeeds, false if it fails */ public boolean sendDataZRTP(byte[] data) { int totalLength = ZRTP_PACKET_HEADER + data.length; byte[] tmp = new byte[totalLength]; System.arraycopy(data, 0, tmp, ZRTP_PACKET_HEADER, data.length); ZrtpRawPacket packet = new ZrtpRawPacket(tmp, 0, tmp.length); packet.setSSRC(ownSSRC); packet.setSeqNum(senderZrtpSeqNo++); packet.setCrc(); try { zrtpConnector.getDataOutputStream().write( packet.getBuffer(), packet.getOffset(), packet.getLength()); } catch (IOException e) { logger.warn("Failed to send ZRTP data."); if (logger.isDebugEnabled()) logger.debug("Failed to send ZRTP data.", e); return false; } return true; } /** * * @see gnu.java.zrtp.ZrtpCallback#srtpSecretsReady( * gnu.java.zrtp.ZrtpSrtpSecrets, * gnu.java.zrtp.ZrtpCallback.EnableSecurity) */ public boolean srtpSecretsReady(ZrtpSrtpSecrets secrets, EnableSecurity part) { SRTPPolicy srtpPolicy = null; if (part == EnableSecurity.ForSender) { // To encrypt packets: initiator uses initiator keys, // responder uses responder keys // Create a "half baked" crypto context first and store it. This is // the main crypto context for the sending part of the connection. if (secrets.getRole() == Role.Initiator) { srtpPolicy = new SRTPPolicy(SRTPPolicy.AESCM_ENCRYPTION, secrets.getInitKeyLen() / 8, // key length SRTPPolicy.HMACSHA1_AUTHENTICATION, 20, // auth key length secrets.getSrtpAuthTagLen() / 8,// auth tag length secrets.getInitSaltLen() / 8 // salt length ); SRTPTransformEngine engine = new SRTPTransformEngine(secrets .getKeyInitiator(), secrets.getSaltInitiator(), srtpPolicy, srtpPolicy); srtpOutTransformer = engine.getRTPTransformer(); } else { srtpPolicy = new SRTPPolicy(SRTPPolicy.AESCM_ENCRYPTION, secrets.getRespKeyLen() / 8, // key length SRTPPolicy.HMACSHA1_AUTHENTICATION, 20, // auth key length secrets.getSrtpAuthTagLen() / 8,// auth taglength secrets.getRespSaltLen() / 8 // salt length ); SRTPTransformEngine engine = new SRTPTransformEngine(secrets .getKeyResponder(), secrets.getSaltResponder(), srtpPolicy, srtpPolicy); srtpOutTransformer = engine.getRTPTransformer(); } } if (part == EnableSecurity.ForReceiver) { // To decrypt packets: initiator uses responder keys, // responder initiator keys // See comment above. if (secrets.getRole() == Role.Initiator) { srtpPolicy = new SRTPPolicy(SRTPPolicy.AESCM_ENCRYPTION, secrets.getRespKeyLen() / 8, // key length SRTPPolicy.HMACSHA1_AUTHENTICATION, 20, // auth key length secrets.getSrtpAuthTagLen() / 8,// auth tag length secrets.getRespSaltLen() / 8 // salt length ); SRTPTransformEngine engine = new SRTPTransformEngine(secrets .getKeyResponder(), secrets.getSaltResponder(), srtpPolicy, srtpPolicy); srtpInTransformer = engine.getRTPTransformer(); } else { srtpPolicy = new SRTPPolicy(SRTPPolicy.AESCM_ENCRYPTION, secrets.getInitKeyLen() / 8, // key length SRTPPolicy.HMACSHA1_AUTHENTICATION, 20, // auth key length secrets.getSrtpAuthTagLen() / 8,// auth tag length secrets.getInitSaltLen() / 8 // salt length ); SRTPTransformEngine engine = new SRTPTransformEngine(secrets .getKeyInitiator(), secrets.getSaltInitiator(), srtpPolicy, srtpPolicy); srtpInTransformer = engine.getRTPTransformer(); } } return true; } /** * * @see gnu.java.zrtp.ZrtpCallback#srtpSecretsOn(java.lang.String, * java.lang.String, boolean) */ public void srtpSecretsOn(String c, String s, boolean verified) { if (securityEventManager != null) { securityEventManager.secureOn(c); } if (securityEventManager != null && s != null) { securityEventManager.showSAS(s, verified); } } /** * * @see gnu.java.zrtp.ZrtpCallback#srtpSecretsOff( * gnu.java.zrtp.ZrtpCallback.EnableSecurity) */ public void srtpSecretsOff(EnableSecurity part) { if (part == EnableSecurity.ForSender) { srtpOutTransformer = null; } if (part == EnableSecurity.ForReceiver) { srtpInTransformer = null; } if (securityEventManager != null) { securityEventManager.secureOff(); } } /** * * @see gnu.java.zrtp.ZrtpCallback#activateTimer(int) */ public int activateTimer(int time) { if (timeoutProvider != null) { timeoutProvider.requestTimeout(time, this); } return 1; } /** * * @see gnu.java.zrtp.ZrtpCallback#cancelTimer() */ public int cancelTimer() { if (timeoutProvider != null) { timeoutProvider.cancelRequest(); } return 1; } /** * Timeout handling function. * Delegates the handling to the ZRTP engine. */ public void handleTimeout() { if (zrtpEngine != null) { zrtpEngine.processTimeout(); } } /** * * @see gnu.java.zrtp.ZrtpCallback#sendInfo( * gnu.java.zrtp.ZrtpCodes.MessageSeverity, * java.util.EnumSet) */ public void sendInfo(ZrtpCodes.MessageSeverity severity, EnumSet<?> subCode) { if (securityEventManager != null) { securityEventManager.showMessage(severity, subCode); } } /** * * @see gnu.java.zrtp.ZrtpCallback#zrtpNegotiationFailed( * gnu.java.zrtp.ZrtpCodes.MessageSeverity, * java.util.EnumSet) */ public void zrtpNegotiationFailed(ZrtpCodes.MessageSeverity severity, EnumSet<?> subCode) { if (securityEventManager != null) { securityEventManager.zrtpNegotiationFailed(severity, subCode); } } /** * * @see gnu.java.zrtp.ZrtpCallback#goClearProcedureFailed( * gnu.java.zrtp.ZrtpCodes.MessageSeverity, * java.util.EnumSet, boolean) */ public void goClearProcedureFailed(ZrtpCodes.MessageSeverity severity, EnumSet<?> subCode, boolean maintainSecurity) { // if (userCallback != null) // { // userCallback.goClearProcedureFailed(severity, // subCode, maintainSecurity); // } } /** * * @see gnu.java.zrtp.ZrtpCallback#zrtpNotSuppOther() */ public void zrtpNotSuppOther() { if (securityEventManager != null) { securityEventManager.zrtpNotSuppOther(); } } /** * @see gnu.java.zrtp.ZrtpCallback#zrtpAskEnrollment(java.lang.String) */ public void zrtpAskEnrollment(String info) { if (securityEventManager != null) { securityEventManager.zrtpAskEnrollment(info); } } /** * * @see gnu.java.zrtp.ZrtpCallback#zrtpInformEnrollment(java.lang.String) */ public void zrtpInformEnrollment(String info) { if (securityEventManager != null) { securityEventManager.zrtpInformEnrollment(info); } } /** * * @see gnu.java.zrtp.ZrtpCallback#signSAS(java.lang.String) */ public void signSAS(String sas) { if (securityEventManager != null) { securityEventManager.signSAS(sas); } } /** * * @see gnu.java.zrtp.ZrtpCallback#checkSASSignature(java.lang.String) */ public boolean checkSASSignature(String sas) { return ((securityEventManager != null) ? securityEventManager.checkSASSignature(sas) : false); } /** * Sets the enableZrtp flag. * * @param onOff The value for the enableZrtp flag. */ public void setEnableZrtp(boolean onOff) { enableZrtp = onOff; } /** * Returns the enableZrtp flag. * * @return the enableZrtp flag. */ public boolean isEnableZrtp() { return enableZrtp; } /** * Set the SAS as verified internally if the user confirms it */ public void SASVerified() { if (zrtpEngine != null) zrtpEngine.SASVerified(); } /** * Resets the internal engine SAS verified flag */ public void resetSASVerified() { if (zrtpEngine != null) zrtpEngine.resetSASVerified(); } /** * Method called when the user requests through GUI to switch a secured call * to unsecure mode. Just forwards the request to the Zrtp class. */ public void requestGoClear() { // if (zrtpEngine != null) // zrtpEngine.requestGoClear(); } /** * Method called when the user requests through GUI to switch a previously * unsecured call back to secure mode. Just forwards the request to the * Zrtp class. */ public void requestGoSecure() { // if (zrtpEngine != null) // zrtpEngine.requestGoSecure(); } /** * Sets the srtps secret data (chapter 3.2.1 in the ZRTP specification) * * @param data The srtps secret data */ public void setSrtpsSecret(byte[] data) { if (zrtpEngine != null) zrtpEngine.setSrtpsSecret(data); } /** * Sets the other secret data (chapter 3.2.1 in the ZRTP specification) * * @param data The other secret data */ public void setOtherSecret(byte[] data) { if (zrtpEngine != null) zrtpEngine.setOtherSecret(data); } /** * Sets the client ID * * @param id The client ID */ public void setClientId(String id) { clientIdString = id; } /** * Gets the Hello packet Hash * * @return the Hello packet hash */ public String getHelloHash() { if (zrtpEngine != null) return zrtpEngine.getHelloHash(); else return new String(); } /** * Gets the multistream params * * @return the multistream params */ public byte[] getMultiStrParams() { if (zrtpEngine != null) return zrtpEngine.getMultiStrParams(); else return new byte[0]; } /** * Sets the multistream params * (The multistream part needs further development) * @param parameters the multistream params */ public void setMultiStrParams(byte[] parameters) { if (zrtpEngine != null) { zrtpEngine.setMultiStrParams(parameters); multiStream = true; } } /** * Gets the multistream flag * (The multistream part needs further development) * @return the multistream flag */ public boolean isMultiStream() { return ((zrtpEngine != null) ? zrtpEngine.isMultiStream() : false); } /** * Used to accept a PBX enrollment request * (The PBX part needs further development) * @param accepted The boolean value indicating if the request is accepted */ public void acceptEnrollment(boolean accepted) { if (zrtpEngine != null) zrtpEngine.acceptEnrollment(accepted); } /** * Sets signature data for the Confirm packets * * @param data the signature data * @return true if signature data was successfully set */ public boolean setSignatureData(byte[] data) { return ((zrtpEngine != null) ? zrtpEngine.setSignatureData(data) : false); } /** * Gets signature data * * @return the signature data */ public byte[] getSignatureData() { if (zrtpEngine != null) return zrtpEngine.getSignatureData(); else return new byte[0]; } /** * Gets signature length * * @return the signature length */ public int getSignatureLength() { return ((zrtpEngine != null) ? zrtpEngine.getSignatureLength() : 0); } /** * Sets the PBX enrollment flag (see chapter 8.3 of ZRTP standards) * (The PBX part needs further development) * @param yesNo The PBX enrollment flag */ public void setPBXEnrollment(boolean yesNo) { if (zrtpEngine != null) zrtpEngine.setPBXEnrollment(yesNo); } /** * Method called by the Zrtp class as result of a GoClear request from the * other peer. An explicit user confirmation is needed before switching to * unsecured mode. This is asked through the user callback. */ public void handleGoClear() { securityEventManager.confirmGoClear(); } /** * Sets the RTP connector using this ZRTP engine * (This method should be changed to an addConnector to a connector array * managed by the engine for implementing multistream mode) * * @param connector the connector to set */ public void setConnector(TransformConnector connector) { zrtpConnector = connector; } /** * Sets the user callback class used to maintain the GUI ZRTP part * * @param ub The user callback class */ public void setUserCallback(SecurityEventManager ub) { securityEventManager = ub; } /** * Returns the current status of the ZRTP engine * * @return the current status of the ZRTP engine */ public boolean isStarted() { return started; } /* * (non-Javadoc) * @see gnu.java.zrtp.ZrtpCallback#stopStreaming(boolean) */ public void stopStreaming(boolean stop) { holdFlag = stop; } /** * Gets the user callback used to manage the GUI part of ZRTP * * @return the user callback */ public SecurityEventManager getUserCallback() { return securityEventManager; } /** * Get other party's ZID (ZRTP Identifier) data * * This functions returns the other party's ZID that was receivied * during ZRTP processing. * * The ZID data can be retrieved after ZRTP receive the first Hello * packet from the other party. The application may call this method * for example during SAS processing in showSAS(...) user callback * method. * * @return the ZID data as byte array. */ public byte[] getZid() { return ((zrtpEngine != null) ? zrtpEngine.getZid() : null); } }