Insert code to enable secure video streams via ZRTP key negotiation (ZRTP multi-stream mode).

cusax-fix
Werner Dittmann 17 years ago
parent d8c9db8af9
commit 45d35e5d34

@ -243,7 +243,7 @@ public class CallSessionImpl
};
/**
* Additional info codes for ZRTP4J.
* Additional info codes for and data to support ZRTP4J.
* These could be added to the library. However they are specific for this
* implementation, needing them for various GUI changes.
*/
@ -254,6 +254,14 @@ public static enum ZRTPCustomInfoCodes
ZRTPEngineInitFailure;
}
/**
* Holds the "Master" ZRTP session.
*
* This session must be started first and must have negotiated the key material
* before any other media session to the same client can be started. See the
* ZRTP specification, topic multi-streaming mode.
*/
private TransformConnector zrtpDHSession = null;
/**
* JMF stores CUSTOM_CODEC_FORMATS statically, so they only need to be
* registered once. FMJ does this dynamically (per instance), so it needs
@ -509,12 +517,8 @@ private boolean stopStreaming(RTPManager rtpManager)
}
//remove targets
if (selectedKeyProviderAlgorithm != null
/* TODO: Video securing related code
* remove the next condition as part of enabling video securing
* (see comments in secureStatusChanged method for more info)
*/
&& rtpManager.equals(audioRtpManager))
if (selectedKeyProviderAlgorithm != null && selectedKeyProviderAlgorithm.getProviderType()
== KeyProviderAlgorithm.ProviderType.ZRTP_PROVIDER)
{
TransformConnector transConnector =
this.transConnectors.get(rtpManager);
@ -523,10 +527,8 @@ private boolean stopStreaming(RTPManager rtpManager)
{
ZRTPTransformEngine engine
= (ZRTPTransformEngine)transConnector.getEngine();
engine.sendInfo(
ZrtpCodes.MessageSeverity.Info,
EnumSet.of(ZRTPCustomInfoCodes.ZRTPDisabledByCallEnd));
engine.stopZrtp();
engine.cleanup();
transConnector.removeTargets();
}
@ -1257,13 +1259,7 @@ private void initStreamTargets(Connection globalConnParam,
try
{
if (selectedKeyProviderAlgorithm != null
/* TODO: Video securing related code
* remove the next condition as part of enabling video
* securing (see comments in secureStatusChanged method
* for more info)
*/
&& rtpManager.equals(audioRtpManager))
if (selectedKeyProviderAlgorithm != null)
{
TransformConnector transConnector =
this.transConnectors.get(rtpManager);
@ -2050,26 +2046,40 @@ private void initializeRtpManager(RTPManager rtpManager,
// Selected key management type == ZRTP branch
if (selectedKeyProviderAlgorithm != null &&
selectedKeyProviderAlgorithm.getProviderType()
== KeyProviderAlgorithm.ProviderType.ZRTP_PROVIDER
/* TODO: Video securing related code
* remove the next condition as part of enabling video securing
* (see comments in secureStatusChanged method for more info)
*/
&& rtpManager.equals(audioRtpManager))
== KeyProviderAlgorithm.ProviderType.ZRTP_PROVIDER)
{
// Set a ZRTP connector to use for communication
TransformConnector transConnector = null;
TransformManager.initializeProviders();
// The connector is created based also on the crypto services
// The crypto provider solution should be queried somehow
// or taken from a resources file
transConnector = TransformManager.createZRTPConnector(
TransformConnector transConnector = TransformManager.createZRTPConnector(
bindAddress, "BouncyCastle", this);
rtpManager.initialize(transConnector);
this.transConnectors.put(rtpManager, transConnector);
SCCallback callback = new SCCallback(this);
boolean zrtpAutoStart = false;
// Decide if this will become the ZRTP Master session:
// - Statement: audio media session will be started before video media session
// - if no other audio session was started before then this will become
// ZRTP Master session
// - only the ZRTP master sessions start in "aut-sensing" mode to
// immedialtely catch ZRTP communication fro other client
// - after the master session has completed key negotiations it will
// start other media sessions (see SCCallback)
if (rtpManager.equals(audioRtpManager)) {
if (zrtpDHSession == null) {
zrtpDHSession = transConnector;
zrtpAutoStart = true;
callback.setDHSession(true);
}
callback.setType(SecurityGUIEventZrtp.AUDIO);
}
else if (rtpManager.equals(videoRtpManager)) {
callback.setType(SecurityGUIEventZrtp.VIDEO);
}
// ZRTP engine initialization
// TODO: 1. must query/randomize/find a method for the zid file
// name
@ -2077,12 +2087,12 @@ private void initializeRtpManager(RTPManager rtpManager,
ZRTPTransformEngine engine
= (ZRTPTransformEngine)transConnector.getEngine();
engine.setUserCallback(new SCCallback(this));
engine.setUserCallback(callback);
// Case 1: user toggled secure communication prior to the call
if (usingSRTP)
{
if (!engine.initialize("GNUZRTP4J.zid"))
if (!engine.initialize("GNUZRTP4J.zid", zrtpAutoStart))
engine.sendInfo(
ZrtpCodes.MessageSeverity.Info,
EnumSet.of(
@ -2164,6 +2174,7 @@ private void initializeRtpManager(RTPManager rtpManager,
}
catch (Exception exc)
{
exc.printStackTrace();
logger.error("Failed to init an RTP manager.", exc);
throw new MediaException("Failed to init an RTP manager."
, MediaException.IO_ERROR
@ -2786,10 +2797,15 @@ public void setSecureCommunicationStatus(boolean activator,
}
}
/*
* The following methods are specific to ZRTP key management implementation.
*/
/*
* (non-Javadoc)
* @see net.java.sip.communicator.service.media.CallSession#setZrtpSASVerification(boolean)
*/
public boolean setZrtpSASVerification(boolean verified) {
TransformConnector transConnector = this.transConnectors
.get(audioRtpManager);
ZRTPTransformEngine engine = (ZRTPTransformEngine) transConnector
ZRTPTransformEngine engine = (ZRTPTransformEngine) zrtpDHSession
.getEngine();
if (verified) {
engine.SASVerified();
@ -2844,6 +2860,39 @@ private void zrtpChangeStatus(RTPManager manager, SecureEvent event)
}
}
/**
* Start multi-stream ZRTP sessions.
*
* After the ZRTP Master (DH) session reached secure state the SCCallback calls
* this method to start the multi-stream ZRTP sessions.
*
* First get the multi-stream data from the ZRTP DH session. Then iterate over
* all known connectors, set multi-stream mode data, and enable auto-start
* mode (auto-sensing).
*
* @return Number of started ZRTP multi-stream mode sessions
*/
public int startZrtpMultiStreams() {
ZRTPTransformEngine engine
= (ZRTPTransformEngine)zrtpDHSession.getEngine();
int counter = 0;
byte[] multiStreamData = engine.getMultiStrParams();
Enumeration<TransformConnector> tcs = transConnectors.elements();
while (tcs.hasMoreElements()) {
TransformConnector tc = tcs.nextElement();
if (tc.equals(zrtpDHSession)) {
continue;
}
engine = (ZRTPTransformEngine)tc.getEngine();
engine.setMultiStrParams(multiStreamData);
engine.setEnableZrtp(true);
counter++;
}
return counter;
}
/**
* Initializes the supported key management types and establishes
* default usage priorities for them.

@ -8,6 +8,7 @@
import java.util.*;
import net.java.sip.communicator.impl.media.CallSessionImpl;
import net.java.sip.communicator.service.media.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.Logger;
@ -36,7 +37,17 @@ public class SCCallback
private SecurityGUIListener guiListener = null;
private CallParticipant participant;
/*
* Is this a ZRTP DH (Master) session?
*/
private boolean dhSession = false;
/*
* Type of session. See class SecurityGUIEventZrtp which types are
* supported.
*/
private String sessionType = null;
/**
* The class constructor.
*/
@ -57,7 +68,8 @@ public void init() {
SecurityGUIEvent.NONE,
SecurityGUIEvent.SECURITY_ENABLED);
logger.info("initialize SCCallback");
if (logger.isInfoEnabled())
logger.info(sessionType +": initialize SCCallback");
fireStateChangedEvent(evt);
}
@ -73,16 +85,41 @@ private void fireStateChangedEvent(SecurityGUIEvent evt) {
}
}
/**
* Set the type of this session.
*
* @param type
*/
public void setType(String type) {
sessionType = type;
}
/**
* Set the DH session flag.
*
* @param yesNo
*/
public void setDHSession(boolean yesNo) {
dhSession = yesNo;
}
/*
* The following methods implement the ZrtpUserCallback interface
*/
/*
* (non-Javadoc)
* @see gnu.java.zrtp.ZrtpUserCallback#secureOn(java.lang.String)
*/
public void secureOn(String cipher)
{
logger.info("Cipher: " + cipher);
if (logger.isInfoEnabled())
logger.info(sessionType + ": cipher enabled: " + cipher);
HashMap<String, Object> state = new HashMap<String, Object>(3);
state.put(SecurityGUIEventZrtp.SESSION_TYPE, SecurityGUIEventZrtp.AUDIO);
state.put(SecurityGUIEventZrtp.SESSION_TYPE, sessionType);
state.put(SecurityGUIEventZrtp.SECURITY_CHANGE, Boolean.TRUE);
state.put(SecurityGUIEventZrtp.CIPHER, cipher);
@ -96,7 +133,9 @@ public void secureOn(String cipher)
*/
public void showSAS(String sas, boolean verified)
{
logger.info("SAS: " + sas);
if (logger.isInfoEnabled())
logger.info(sessionType + ": SAS is: " + sas);
HashMap<String, Object> state = new HashMap<String, Object>(3);
state.put(SecurityGUIEventZrtp.SESSION_TYPE, SecurityGUIEventZrtp.AUDIO);
@ -118,11 +157,33 @@ public void showSAS(String sas, boolean verified)
* gnu.java.zrtp.ZrtpCodes.MessageSeverity,
* java.util.EnumSet)
*/
public void showMessage(ZrtpCodes.MessageSeverity sev, EnumSet<?> subCode)
{
public void showMessage(ZrtpCodes.MessageSeverity sev, EnumSet<?> subCode) {
ZrtpCodes.InfoCodes inf;
int multiStreams = 0;
Iterator<?> ii = subCode.iterator();
Object msgCode = ii.next();
logger.info("Show message sub code: " + msgCode);
if (sev == ZrtpCodes.MessageSeverity.Info) {
if (msgCode instanceof ZrtpCodes.InfoCodes) {
inf = (ZrtpCodes.InfoCodes) msgCode;
// If the ZRTP Master session (DH mode) signals "security on"
// then start multi-stream sessions.
if (dhSession && inf == ZrtpCodes.InfoCodes.InfoSecureStateOn) {
multiStreams = ((CallSessionImpl) callSession)
.startZrtpMultiStreams();
}
}
}
if (logger.isInfoEnabled()) {
logger.info(sessionType + ": " + "ZRTP message: severity: " + sev
+ ", sub code: " + msgCode + ", DH session: " + dhSession
+ ", multi: " + multiStreams);
}
}
/*
@ -136,7 +197,9 @@ public void zrtpNegotiationFailed(ZrtpCodes.MessageSeverity severity,
{
Iterator<?> ii = subCode.iterator();
Object msgCode = ii.next();
logger.warn("Negotiation failed sub code: " + msgCode);
if (logger.isInfoEnabled())
logger.warn(sessionType + ": ZRTP key negotiation failed, sub code: " + msgCode);
}
/*
@ -145,7 +208,8 @@ public void zrtpNegotiationFailed(ZrtpCodes.MessageSeverity severity,
*/
public void secureOff()
{
logger.info("Security off");
if (logger.isInfoEnabled())
logger.info(sessionType + ": Security off");
HashMap<String, Object> state = new HashMap<String, Object>(2);
@ -162,7 +226,8 @@ public void secureOff()
*/
public void zrtpNotSuppOther()
{
logger.info("ZRTP not supported");
if (logger.isInfoEnabled())
logger.info(sessionType + ": Other party does not support ZRTP key negotiation protocol, no secure calls possible");
}
/*
@ -171,6 +236,7 @@ public void zrtpNotSuppOther()
*/
public void confirmGoClear()
{
logger.info("GoClear confirmation requested");
if (logger.isInfoEnabled())
logger.info(sessionType + ": GoClear confirmation requested");
}
}

@ -362,7 +362,7 @@ public PacketTransformer getRTPTransformer()
/**
* Default engine initialization method.
* Calling this for engine initialization starts it with auto-sensing.
* 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
@ -445,7 +445,6 @@ public synchronized boolean initialize(String zidFilename,
if (zf.open(zidFilename) < 0)
{
enableZrtp = false;
return false;
}
}
@ -459,6 +458,7 @@ public synchronized boolean initialize(String zidFilename,
{
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
userCallback.init();

Loading…
Cancel
Save