Thursday, July 21, 2011

BerrySync: Untested code is broken code

TLDR - What did I learn?

In the irc channels I lurk, a phrase reigns true. "Untested code is broken code". I overlooked this bug because my tests didn't keep up with the code. Don't be lazy, you will not remember you took short cuts a month ago.

BerrySync's Show Stopper
So I'm very quick to point fingers, So naturally when our program stops decrypting 75% of the I went straight to You should note RIM is abiding by this document and if you read further down you'll note that this algorithm padding standard does not mention AES encryption which is tragic because its the only symmetric key unformatter engine that RIM supplies, meaning you'll need it for AES encryption! For example BerrySync's crypto module sans error control:

AESKey key = new AESKey(keyData);
InitializationVector iv = new InitializationVector(ivData);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BlockEncryptor encryptor = new BlockEncryptor(
     new PKCS5FormatterEngine(
          new AESCBCEncryptorEngine(key, iv)), outputStream);
return outputStream.toByteArray(); 

I And you should check out Here you'll see that Mozilla is abiding to The 2.1 standard includes AES encryption in the spec, hold on a minute. RIM must be doing something totally off the wall here. All of that combined with the knowledge that using third party and unlicensed encryption and getting your app into AppWorld would involve many headaches and much money ala ECCN.


As with most things my finger pointing was wrong, the bug actually lived on this line
data = data.replace('-', '\0'); 
Where my lazy attempt at removing characters from a string totally backfired. The interesting thing is that during rare cases, my sync account and about 25% of others tested it didn't actually make a difference and everything worked as intended. Where the other 75% of accounts saw a Bad Padding Exception during decryption.

Wednesday, July 6, 2011

BerrySync: How fetcher gets it done, thread pooling

A Little Bit Of Background
I designed My fetcher library to have modules, these house the logic for the various steps I would need to perform. The fetcher itself links up the modules and goes from a url to a usable object for BerrySync.

One of the more troublesome modules was the Smuggler, I originally designed smuggler to do the network scheduling for fetcher then Smugglers worker thread would perform the actual connections, making the operation non-blocking(which is important for a good user experience!).

I was forced to change the design, because the data parsing and decryption had to moved off the main thread. To facilitate this I gave Fetcher its own internal work Queue, with the smuggler still scheduling the network connections this time using Fetchers new and improved .invokeLater(runnable r) method!

public void invokeLater(Runnable work){
private final class WorkQueue {
        private Node _head;
        private Node _tail;
        private QueueWorker[] _worker;
        public WorkQueue(){...} 
        public synchronized void enQueue(Runnable data) {...}
        private synchronized Runnable deQueue() 
throws InterruptedException{...}
        private final class QueueWorker extends Thread {
            public void run() {
                Runnable work = null;
                while (true) {
                    try {
                        work = deQueue();
                    catch (InterruptedException ignored) {}

I'm using the runnable interface to formalize how this thread can 'run' your work. The commented out methods just show a simple queue linked list data structure.

Tune In Next Time
In the next instalment I'll tell you all about how I'm tracking down an elusive decryption bug with sync data on the BlackBerry!