The code modifications since last week can be found here:
- .patch format: http://students.info.uaic.ro/~eonica/sc/zrtp02.patch
- zip archive: http://students.info.uaic.ro/~eonica/sc/patch02.zip
- actual created/modified sources: http://students.info.uaic.ro/~eonica/sc/patch02/
These contain also Werner's sources ( that's the reason for their size :) ), about which I'll talk a bit later.
I'll detail now what I've managed to do since last week. I've changed a bit the steps discussed - more exactly, I've started focusing on the GUI part before actual finishing the library integration (where actual finishing = mainly eliminating bugs) because the GUI actions are related to triggering ZRTP startup.
So, I'll start explaining how things work from the point where the user activates the secure communication until the library code is used. I think it will be more clear this way.
I decided to activate the secure communication (and when I tell secure - I mean it in a general way, not directly related to ZRTP) through a button on the main quick menu toolbar. Actually I had an initial idea, which I started to develop to add this button and the additional ZRTP specific features (like a SAS label) through a ZRTP GUI plugin. But it didn't seem right because first of all - like I said - the button isn't actually related only to ZRTP, and above all it has a pretty general/important function by triggering secure communication from the media package. So I've decided to separate it from the ZRTP GUI part (about which I need a feedback on how and more important where it's prefered to be added; I'll detail later). In conclusion, I've added the specific button and it's handler to the QuickMenu class. I've also added the ability to provide the media service on the GUIActivator, the media service being used in the QuickMenu class by the button handler to set a general secure on/off communication parameter. That's about all the modifications I've done inside the GUI part of SC. I hope I wasn't very "invasive" :). You can see how it looks by running SC or in the next screenshot:
(1. I won't mind if you don't agree with my button "design" and somebody repaints it :) and 2. I really don't know why the mouse cursor wasn't caught in the screenshot but I assure you the tooltip appears because it's there :) )
I'l continue now with the way the code "flows" starting from the button and I'll be back to GUI in the end. Like I said, the button sets a general parameter to toggle communication security on and off. This parameter is actually the usingSRTP boolean member of CallSessionImpl for which I've changed a bit the role as it follows.
There are two distinct moments when the user could toggle the secure status on or off.
1. There isn't any call going on
In this case any call that follows the on/off secure setting made by user should use that setting by default to choose what kind of call - secure/unsecured - to start (e.g.: the user starts SC - lets' say usingSRTP is false by default, toggles secure communication on - usingSRTP true, makes a call - the call will be secured). The problem was that usingSRTP was an instance variable so it didn't exist until the call was created and in the above example it should be set before this happens. The solutions were to make it static or to pass it as a parameter at call session creation by moving it in the MediaServiceImpl. I decided for the first solution to keep as much as possible in the call session and to interact less with the media service. Anyway this can be discussed (with respect to section 2. below), because the value setting for usingSRTP at a button click is still done by using a getter and a setter exported by the media service. I didn't see other entry point possible for the Call Session.
2. There is a call going on
This will be the case when the user is involved in a call and decides to change the secure status for the communication (e.g. : GoClear in ZRTP from secure to normal stream or GoSecure from normal stream to secure). The same thing as before happens with the usingSRTP parameter, but this time also an event will be received by the CallSessionImpl instances notifying that a change in the security status is indicated. I've designed a SecureEventListener/SecureEvent mechanism for this. More exactly the CallSessionImpl implements the secure listener and registers itself as it's own listener in the callStateChanged method when CALL_IN_PROGRESS is received - when call starts, and removes itself from the listeners Vector in the same method at CALL_ENDED when the call ends. So, between these two moments the CallSession will handle, in the secureStatusChanged method, any usingSRTP secure/unsecure modification triggered by the user through the GUI.
Now, like I said in the start, usingSRTP is exactly what it sounds like = using SRTP general indication independent of the key management solution, and the behaviour described above respects also this, which keeps open the posibility of future adding other key sharing solutions. For this, a very basic approach (which should be further developed) is the small implementation done in the keyshare package, which was present also in the last patch, but I've modified it a bit by changing the names to keep it more distinct to the cryptography services providers, and also added a priority field. This should be used in a more advanced algorithm in case of more than one key management systems are present, to select which of them should be used. For now ZRTP being the only one considered, it has the highest priority :). The key management type to be used is being held in the selectedKeyProviderAlgorithm. Actually, this is, I might say the point where the implementation gets different, until now being based on general secure on and off. Based on this selectedKeyProviderAlgorithm type (which might be for now ZRTP, Dummy hardcoded SRTP keys or none) the few general actions in CallSessionImpl related with communication securing are performed different. For example the handling of the SecureEvent during a call which announces a change in the secure mode is ignored in case of Dummy hardcoded SRTP or no securing algorithm, and the Go Clear or Go Secure actions are performed only in case of ZRTP. About this, I've used Werner's ZRTPTransformEngine startZrtp and stopZrtp for now to have some handling methods there, but for stopZrtp I know it's not exactly what is needed for GoClear. About startZrtp I'm not sure if it's ok or not for a GoSecure, after a previous GoClear, as I didn't manage to get deeper yet into the code and compare it with the ZRTP standard, but I suppose it's close :). Anyway, I didn't manage to make a succesfully test yet to see how it actually works (I'll tell in the end where I'm stuck now).
Well, I've reached the point where I should talk about how Werner's library is integrated besides the mentions made on GoSecure/GoClear above. It's not very much to tell. Essentially I've followed the steps on Werner's demo package and adapted to the CallSessionImpl class ( it took more figuring how I'll use Werner's modified SRTP packages :) ). So, the integration (as it's now implemented) could be resumed in the next ideas:
- based on the selectedKeyProviderAlgorithm type in the initializeRtpManager a ZRTP connector is created by calling the specific function from the TransformManager, after which the RTP Manager is initialized with the connector as parameter
- ZRTP is actually started in the update methods for the ReceiveStream and SendStream events (in case events are new stream events) by getting the engine instance from the connector and calling startZrtp; I've added an isStarted getter to Werner's ZRTPEngine for this in order not to call the startZrtp method in both of the update handlers; I'm new to JMF and to Werner's code also and I'm not sure if all this is actually OK (I still have some bugs before this point and didn't reached it yet) so some feedback after looking into the sources will be welcome
- The same startZrtp (and for now stopZrtp) is called also as said before, for handling any during-call-security-status-change-events
- Werner added the option of choosing a custom Java Security Provider for cryptographic services and modified the SRTP packages accordingly, so I've added in the TransformManager class two functions for minimum support of this customization, somehow similar to the way I've dealed with the custom key management system described above; the functions are initializeProviders which should query the current supported security services providers, and selectProvider which should select one of them for usage; of course for now only one option here too - BouncyCastle; any way the mentioned functions should be further developed and also I'm not sure the way I've integrated them now it's the best approach possible; also related to this I've added a cryptoProvider parameter to the createZrtpConnector too
- The createZrtpConnector function in the TransformManager practically concludes the access to the library instantiating a ZRTPTransformEngine, selecting a cryptography services provider, creating the connector, and making the necessary initializations in the engine (setConnector, setUserCallback, setCryptoProvider)
About the user callback initialization of the ZRTP engine - I've defined a SCCallback class in the keyshare.zrtp package to be used for this, class which resembles pretty much the internal MyCallback class from Werner's demo package. The difference is that I've provided GUI access in it by getting a UIService reference from the BundleContext provided by the MediaActivator. From this reference to UIService we easily can bring up popup messages (as all functions do at the moment in the respective class). The problem is that I don't know how this approach will comply with the requirement stated by Werner that I quote: "All methods of the user callback class and classes that extend this class run in the context of the RTP thread. Thus it is of paramount importance to keep the execution time of the methods as short as possible." I'll need some feedback about this from an SC GUI developer, or we should see at testing how it works. Also, popup messages aren't the proper solution for all the GUI interaction parts in that callback class. The SAS message for example should be displayed for the entire call duration I think (or at least it should be possible to do this, correct me if I'm wrong) so a Label or some other GUI element should be added for this to the interface. The main problem for me at this point is where :). To be more clear for a feedback from a GUI developer the SAS message is an authentication string for the current call which the user should be able to check with his peer by voice (we could force the user to check the SAS when it's established through a popup message but I don't recall this being mentioned by the standard :) so this is the reason why we should keep it on for the entire call duration). The string has 4 digits as I recall, but I think it depends on the rendering algorithm (I need some feedback from Werner on this, or I'll take another look in the standard to see exactly). So, like I said, the main problem was where to display this. An idea was in the toolbar near the GoSecure button only when the call is active and security is on. Anyway I don't recall exactly at this moment if there are other GUI elements beside this and various information and confirmation messages. For the last part, as I've read in the tutorial, the UIService provides Confirm dialog and Input Dialog as easy as the popup messages so it shoudn't be a problem. If there are any other elements (of which I don't recall to be at this moment), I'll ask Werner to give some feedback if possible. About how the SAS part will be implemented there are two options - one to add it as I did with the button, or to make a GUI plugin for this. Again I'll need some feedback from a GUI developer. (I left actually some minimum remains from the initial plugin I've started in the sources to develop it as a plugin for a SAS but it seems a bit innapropriate - it may be not, though - to make a plugin for displaying only a label; if there are some other elements it's another story) . One more idea related to the SAS is that if adding it as a JLabel to the QuickMenu isn't possible (maybe, it's not supported) it could be very well added as another (bigger) inactive button on which we can change the caption string. That will be pretty much about the interface issues I face right now.
I left the bigger problems for last. The first of them was the fact that Werner modified the SRTP implementation and added it as component packages to ZRTP4J. So I didn't know what to do as first - to use them directly from ZRTp4J or to override them on the previous SC code. Finally I chose the last, on the reason because after all SRTP might be used by other key management system also, and seemed more appropriate. For now as it can be seen also from the patch, I've modified the SRTP packages in the SC code to Werner's version and added only:
I didn't add the rest because there would be duplicates in the ZRTP4J and SC code. I've also modified the references in the ones mentioned to point to the ones in SC. Like I've said these arent the original SC SRTP packages, I've modified them according to Werner's optimized sources. I also was able to take a look at the modifications Werner did while doing this and I might have some questions (but in another post, after I'll look again at what I didn't understand at the first time). I made a small modification also, by changing a ZrtpUtil package function array comparison call to an inline implementation in order to keep SRTP not depending on the rest of ZRTP library. I know that eventually ZRTP probably should be used as a jar, but for now during the development phase it seems better to integrate it as direct sources (still I don't know if the described approach is the best and I'd like some feedback from Werner and Romain also).
Also about this way of integrating the sources for now, and if this is ok or not, might be related the point where I'm stuck now. To be more clear the packages are added as they were sent by Werner in the mail I've got, moved in the src folder of SC. So the imports are made using import gnu.java.zrtp... The build goes well, but at exec time I got a
java.lang.NoClassDefFoundError: gnu/java/zrtp/jmf/transform/zrtp/ZrtpTransformConnector in CallSessionImpl at the TransformManager.createZRTPConnector call (line 1558) . I'm not stuck at this since very long (so I hope I'll probably figure it out eventually) but until now I don't see a reason for it. The class is built and it is there at the respective path in the bin folder of SC. Maybe I should add some imports in a manifest file, but the Felix console doesn't report any problem related with the gnu packages at runtime so I don't know if the problem resides here. Anyway I'm not very experienced with OSGi to know for sure. Also, I don't think this is a classpath problem, the gnu folder being at the same level with the net folder in src, and the imports are made in similar way. If somebody could provide some help until I'll figure it out, I'll appreciate it very much.
This should be all for the last week (and the beginning of this one also). I'll be waiting for some feedback, until which I'm gonna try getting over the mentioned problem and further testing the current implementation form. Also, I'll try getting the sources posted on the SC dedicated svn branch at java.net until next week.