Tuesday, November 17, 2009

JCOP Smartcard Performance

Abstract
I use NXP JCOP smart-cards for prototyping in my research. I have recently benchmarked the cards using my research code, which contains computational and cryptographic workloads.

I found a couple of surprising results that I want to share, so fellow developers can make informed decisions when choosing their prototyping platforms.

Findings
There is a 1.5-2x speed difference between the different revisions of the same high-end chip, the NXP JCOP41 with 72kb of EEPROM. The V2.2 revision for smart-cards (no longer available, replaced by 2.2.1) has the best performance, and the V2.2.1 revision for the SIM (ID 000) form factor has the worst performance.

There is a significant speed difference between the same revision (V2.2.1) of the same chip (NXP JCOP41, 72kb of EEPROM), in different form factors. The chip for the smart-card form factor is almost as fast as the older V2.2 revision, while the chip for the SIM (ID 000) form factor is significantly slower.

There is a 2-4x speed difference between the same revisions (V2.2, smart-card form factor) of the NXP JCOP31 and the NXP JCOP41 chips.

The 3DES encryption/decryption engine has non-linear performance. The time it takes to decrypt 128 bytes is not very different from the time it takes to decrypt 24 bytes, on the JCOP41 chips. It seems that there is a huge setup cost for the DES engine, which outweighs the actual encryption cost.

There is a 4-8x speed difference between RSA and 3DES encryption on the JCOP41 chips, and a 3x speed difference on the JCOP31 chip. This goes against the conventional wisdom that symmetric encryption is 2 orders of magnitude faster then asymmetric encryption. This is probably due to the time it takes to setup the 3DES engine.

Conclusion
Secure processors in smart-cards have non-obvious performance characteristics. I hope my work saves you from the unpleasant surprises that I had.

Motivation
To the best of my knowledge, there are no easy to get benchmarks on smart-card processors. At least, I couldn't find anything when I searched.

Smart-card retailers disclose vital specifications, like EEPROM size and the cryptographic primitives that are implemented on the chip, but tend to be quiet about speed. The sites I used don't mention anything about the type of processor used, or the frequency of the processor.

For some applications (e.g. prototyping, where I want my unit tests to run quickly), speed is just as critical as the other specifications, and its more important than cost.

Data
The data that I used to reach my conclusions is available below. The benchmarks are described in section 5.1 (page 13) in my paper on a successor to the TPM.

decrypt_3des decrypts 24 bytes of data, while decrypt_3des_long and decrypt_rsa work on 128 bytes of data. 3DES is configured in EDE-CBC mode (112 bits of key material) and uses the ISO-9797 method 2 for padding. RSA decryption uses PCKS#1 padding.

The benchmarks can be reproduced by installing Rubygems, then installing the tem_ruby gem, and issuing the following commands
tem_upload_fw  # Uploads my JavaCard applet to the active smart-card.
tem_bench  # Runs the benchmarks.


NXP JCOP41 v2.2/72k (no longer available)
time_blank_bound_secpack_3des: 0.20757s
time_blank_bound_secpack_rsa: 0.86173s
time_blank_sec: 0.18017s
time_devchip_decrypt_3des: 0.05803s
time_devchip_decrypt_3des_long: 0.08042s
time_devchip_decrypt_rsa_long: 0.74047s
time_post_buffer: 0.08280s
time_simple_apdu: 0.00515s
time_vm_perf: 0.73887s
time_vm_perf_bound_3des: 0.78137s
time_vm_perf_bound_rsa: 1.43647s


NXP JCOP41 v2.2.1/72k (usasmartcard.com product link)
time_blank_bound_secpack_3des: 0.24155s
time_blank_bound_secpack_rsa: 0.89740s
time_blank_sec: 0.18937s
time_devchip_decrypt_3des: 0.08420s
time_devchip_decrypt_3des_long: 0.10800s
time_devchip_decrypt_rsa_long: 0.76480s
time_post_buffer: 0.08577s
time_simple_apdu: 0.00610s
time_vm_perf: 0.83257s
time_vm_perf_bound_3des: 0.90033s
time_vm_perf_bound_rsa: 1.55637s


NXP JCOP41 v2.2.1/72k USB token (usasmartcard.com product link, probably using this card)
time_blank_bound_secpack_3des: 0.41070s
time_blank_bound_secpack_rsa: 1.23089s
time_blank_sec: 0.34530s
time_devchip_decrypt_3des: 0.19010s
time_devchip_decrypt_3des_long: 0.21410s
time_devchip_decrypt_rsa_long: 1.05600s
time_post_buffer: 0.17213s
time_simple_apdu: 0.01000s
time_vm_perf: 1.11310s
time_vm_perf_bound_3des: 1.19703s
time_vm_perf_bound_rsa: 2.01420s


NXP JCOP31 v2.2 (usasmartcard.com product link)
time_blank_bound_secpack_3des: 0.84673s
time_blank_bound_secpack_rsa: 1.78957s
time_blank_sec: 0.78120s
time_devchip_decrypt_3des: 0.23553s
time_devchip_decrypt_3des_long: 0.50060s
time_devchip_decrypt_rsa_long: 1.54990s
time_post_buffer: 0.88864s
time_simple_apdu: 0.02813s
time_vm_perf: 1.84374s
time_vm_perf_bound_3des: 1.92594s
time_vm_perf_bound_rsa: 2.87900s

Saturday, November 14, 2009

Quick Way to See Your Gems' Documentation

Summary
The fastest way to see the RDoc for your installed gems is to type the following command into a terminal, and point your Web browser to the address it returns (usually http://localhost:8808)
gem server

Details
The Web server created by the gem server command contains the RDocs for all the gems you have installed, unless you disabled RDoc generation when you installed your gems.


Motivation
I was used to either searching via Google, or going to a gem's RubyForge page to see the RDoc for the gem.

Initially, it seemed that the bit of effort is worth not having to learn some way to generate and bring up the RDocs myself. To my surprise, the procedure is very simple, and it's totally faster than browsing to some Web site that has the RDocs.

That aside, using a local server has the advantage that you'll see the RDocs corresponding to the exact versions of your gems. And, last but not least, RubyForge seems to be slowly falling into oblivion, and newer gems don't seem to bother publishing their RDocs.

I hope this post saves you some time.

Tuesday, July 28, 2009

Sandbox Push Notifications on Hacktivated iPhones

This post reports my finding that push notifications in the sandbox environment don't work on hacktivated iPhones, even with the Push Fix package.

I spent a lot of time developing code for Push Notifications, because I was debugging my code under the assumption that Push Notifications work on my iPhone. I hope this post saves some time for other iPhone SDK developers.

Test Environment
I used an iPhone 2G (hardware model iPhone1,1) which was never activated with AT&T. The phone was connected to the Internet via WiFi, and it had no SIM card in it. My control is a newly bought iPod Touch 2G (hardware model iPod2,1) was activated with iTunes, upgraded to iPhone OS 3.0, and connected to the Internet via the same WiFi router.

The iPhone was jailbroken, hacktivated, and unlocked with Pwnage Tool 3.0, and it received Push Fix from the iPhoneil.net repository. I used AIM (the free edition) to confirm that Push Notifications work on the iPhone.

I used ZergSupport's test suite to collect the push tokens for the iPhone and iPod, and I used imobile's test suite to send the push notifications.

Test Results
The hacktivated iPhone never received notifications from the sandbox (a.k.a. development) servers. It did receive notifications from the production servers. The iTunes-activated iPod received both development and production notifications.

Conclusion
If you're considering developing for the iPhone, and you want to implement and test Push Notifications for your application, you'll need an iTunes-activated device. The cheapest option is probably an iPod Touch 2G.

Motivation
I can't afford an iPhone. I can afford the device, but I can't afford AT&T's plan. On the other hand, I want to address the iPhone's user base, because it consists of wealthy people who spend money easily.

I have an iPhone 2G, from the good days when you could buy one in an Apple store, and not have to deal with AT&T at all. I like testing my application on its EDGE connection, to ensure they behave under the worst-case network connectivity scenario.

Saturday, July 25, 2009

Rebuild Your Ruby Gems If You Update To Snow Leopard

This post contains a command that you must absolutely issue if you are a Ruby developer upgrading to Snow Leopard.

The Commands
Update: Type the following command in terminal:
sudo gem update --system; sudo gem pristine --all
rubygems will produce some errors which are safe to ignore

For historical reasons, here's my initial solution to re-compiling all the native gems.
Fire up irb, and type the following command:
`gem list`.each_line {|line| system "sudo gem install #{line.split.first}"}

Motivation
Snow Leopard introduces a disrupting change: everything runs in 64-bit mode by default. Most importantly to me, ruby is now 64-bit. This is a problem when upgrading to Snow Leopard, as opposed to doing a fresh install, because the Ruby extensions in your old gems are probably 32-bit.

A quick solution to this problem is getting all the extensions rebuilt, which is done by reinstalling all the gems.

In case you're wondering, gem update won't do the trick, because it will not rebuild all your gems.

Symptoms
If you're lucky, you'll get a library loading error when trying to use some gem with an extension (example: json), and you'll figure out rather quickly that you need to reinstall the gem.

A subtle symptom of the same bug is experiencing slowdowns running a Rails development server. In my case, webrick was really slow - start-up took about 30 seconds. For this reason, it's better to re-compile all the gems, as oppose to fire-fighting load error messages.

I hope this post saves you some time.

Saturday, July 11, 2009

Downloading YouTube videos with TubeTV again

One-line Summary
If the TubeTV download button is disabled in a YouTube video page, refresh the page (Apple+R) and hit the button while it's available.

Whole Story
I use TubeTV to download music videos those funny user-generated videos from YouTube. I've set it to encode the videos for my iPhone, then them directly in my iTunes library, tagged as Music Videos. Amazingly, it was released in early 2008, and it's still avoiding all the crap that has come to YouTube since (annotations, ads). Thank you YouTube for not tampering with the H.264 stream in the Flash files!

I usually wait until the YouTube video loads completely before I hit TubeTV's download button, so I don't download the same bits twice. But, as of recently, I've noticed that the download button becomes disabled at some point during the video's load. I was scared for a second, and thought the days of my easy downloading are over.

After my 2-seconds panic went away, I tried refreshing the page, and the download button was enabled again. The videos are still downloaded, encoded for iPhone, and deposited into iTunes' library just fine.

Closing Thoughts
Too bad TubeTV wasn't open sourced, even though looks like its author abandoned it. One day, it will stop working. Hopefully, something better will be written by then. Or YouTube will start using <video> tags and serve us the H.264 data on a silver platter. And the RIAA / MPAA will let that slide. Right.

Monday, May 25, 2009

Snooping on iPhone Applications

Most iPhone applications communicate with a server to perform their functions. This post is a step-by-step guide for snooping on the communications between the iPhone application and its server. The instructions can come in handy for debugging your own application, or if you're curious how other applications communicate with their servers.

Overview
My method uses Wireshark's WiFi RadioTap promiscuous mode to capture all the radio traffic, and find the iPhone's traffic. This article starts by laying out the necessary "ingredients", and guides you through setting up your iPhone and your Mac. Snooping the traffic is demonstrated by snooping on Apple's Stocks application. The post wraps up by describing my motivation for snooping on iPhone apps.

Ingredients
This post is tailored to my home environment, which is described below. Most differences between that environment and yours can be compensated by a bit of creativity. Here's what you need:
  1. iPhone or iPod Touch. As long as it can run the application and connect to WiFi, it works.
  2. Open WiFi network. Most schools and work places have open guest networks, which work for this purpose. At home, I disable the security on my router/AP for the duration of my snooping, and re-enable it later on.
  3. Mac computer with OSX Leopard. It may work on Tiger, I haven't tried. It may work on hackintoshes, but I haven't tried that either. The software I'm using also has Windows/Linux ports, which I haven't tried.
iPhone / iPod Touch Setup
The iPhone can communicate using the cellular network, in addition to the WiFi. We want to make sure that doesn't happen. The fastest way I know is to go to Settings and enable Airplane Mode, and then select and enable WiFi and re-connect to the access point. If you are using an iPod Touch, you don't have to worry about this: it can only communicate via WiFi.

Snooping on applications is a lot easier if you know your iPhone / iPod's IP address. To find the IP launch Settings, and select WiFi, click on the blue arrow next to your access point's name, and read the IP from under the DHCP tab. This blog post has a thorough guide for this step, with pictures.

Computer Setup
Go to Wireshark's download page and download the stable version .dmg for your computer. The stable version at the time of this writing has all the necessary features for snooping, so you don't need the development version unless you feel adventurous. Yes, I knew you'd ask!

The Wireshark installation is not straightforward yet (this writing uses version 1.12), so I will go through the steps. Start off with the easy part, and drag the Wireshark icon to the Applications folder. The following commands (which you can copy-paste in Terminal) implement the instructions in the Readme.rtf included in the .dmg download.

sudo cp /Volumes/Wireshark/Utilities/Command\ Line/* /usr/local/bin/
sudo cp -r /Volumes/Wireshark/Utilities/ChmodBPF /Library/StartupItems/
sudo /Library/StartupItems/ChmodBPF/ChmodBPF start
You can unmount and delete the .dmg now.

Application Traffic Snooping
Before starting Wireshark, make sure your Mac is using WiFi. I have both LAN and WiFi connections, and I pull out my LAN cable before starting up Wireshark.

Start Wireshark, ignore the dialog boxes (there should be one informing you about a potentially long startup time, and one about missing stuff while loading MIBs). Open the Capture menu, and select Intefaces. Identify your WiFi interface - it's usually en1 (that's always the case on a Macbook / Macbook Pro). Click the Options button, change the Link-layer header type to IEEE 802.11 plus radiotap WLAN header, and enable Promiscuous mode.

Your capture should be as short as possible, to make analysis easy. For this reason, get ready to launch your iPhone application, and launch it as soon as Wireshark starts capturing traffic. Click the Start button at the bottom-right of Wireshark's dialog to start playing.

To stop the capture, select Stop from the Capture menu. For a shortcut, you can use the 4th toolbar icon from the left. If everything went well, all the iPhone traffic is available for your analyzing pleasure.

The example below shows an easy method for looking at an application's traffic.

Apple Stocks Traffic
This section describes how you can observe the traffic of Apple's Stocks application that comes pre-installed on iPhone OS. You can safely skip it if you feel like exploring Wireshark on your own.

First, use the instructions above for capturing the iPhone's Internet traffic for a few seconds, right when Stocks is launched. In the packets table, click on the Source header to sort packets by source. Find the packets originating from your iPhone / iPod Touch. Go through until you find something interesting.

For the Stocks application, the first interesting packet is a DNS resolution request for iphone-wu.apple.com which is the server feeding Stocks its information. The packets right under that are TCP packets, and you can right-click on any of them and Follow TCP stream. You will see a HTTP request / response between the Stocks application and Apple's servers. The imei parameter there caused some uproar (and blog traffic) a couple of years ago, so traffic snooping can definitely pay off.

When you close the TCP stream window, your packets window will only show the packets related to the request / response pair that you just saw. If you look in the Filter field under the toolbar, you can get a glimpse of Wireshark's filter syntax. The filter can be edited. For example, if you remove the predicate consisting of tcp.port eq and some big number, you will have all the HTTP packets between exchanged between the iPhone / iPod Touch and Apple's server.

By now, you should have a good glimpse into Stocks' communication protocol. Of course, the method described here applies to any other application, as long as it doesn't use encryption (e.g. SSL / TLS).

Motivation
I use this method to see where iPhone applications get their data from, and how they communicate with their servers. For example, the Stocks application claims it uses Yahoo data, and I wanted to see if it has a private XML feed, or if it implemented its own JSON parsing.

I also used this method to analyze the protocol of an online game that I like, so that I can write a script for automating the boring tasks.


Thank you for reading this post! I'm looking forward to your feedback. I would especially appreciate comments on simplifying the setup process. Happy snooping!

Wednesday, May 13, 2009

iPhone Web Service Toolkit Upgrade: JSON FTW

I have recently open-sourced the ZergSupport code updates used in StockPlay versions 0.3 and 0.4. The high-visibility high-impact change is support for JSON parsing. This post shows what you can do with JSON parsing.

Compact Collection Initialization
Unfortunately, Objective C does not have literals for collections (arrays, dictionaries, or sets). Setting up complex nested structures normally requires ugly objective C code. Fortunately, the whole JSON specification is a compact literal notation. Compare and contrast the following.



To sweeten the deal even more, ZergSupport's JSON parser was extended so you can conveniently embed literals in Objective C strings. First, strings can be delimited by ' (single quotes) asides from the standard delimiter " (double quotes). Second, the extended parser understands sets, which look like arrays, but are delimited by angled brackets ( < > ) instead of square brackets ( [ ] ). Without further ado, here's how to use JSON literal support.



A small wrinkle to be aware of is that JSON parsing is slower than building the collections directly in Objective C, so JSON literals should be used in features that are not performance-sensistive, like tests and configuration files.

Web Services
The API for working with JSON Web services is very similar to the API for XML services, which is showcased in my first post on ZergSupport. When used from the Web service API, the JSON parser ignores everything up to the first { character, so it is able to parse JSONP output.

The code below is a complete implementation for stock ticker symbol search, using Yahoo Finance. The code uses Object Query (covered below) to indicate which parts of the JSON response should be transformed into ModelSupport models.



Object Query
Object Query implements a domain-specific language (DSL) for retrieving objects from a structure of deeply nested Cocoa collections. Queries are specified as strings, and are performed against the root object in a structure of nested collections. The result of a query is an array of zero or more objects matching the query.

The queries are property names, joined by a separator character (usually /). The first character in the query is the separator character. For example /results/1 matches the value that object['results'][1] would return in JavaScript. The special property names * and ? are inspired from glob expressions: * means the next property may be found in the current object or in some descendant object (some levels deeper in the object graph), whereas ? means the next property may be found in the current object or in the object's direct children (one level deeper in the object graph). For example /?/1 will return the same result as /results/1, if the initial object is {'results':['Jane','John']} (the result will be a NSArray containing the NSString @"John").

ObjectQuery can be used directly, outside of JsonHttpRequest, as shown in the following code sample.



The decision to introduce a DSL is motivated by the need to extract ModelSupport models from JSON Web service responses. XML objects have a tag/content separation, and tags are usually good indicators for model extraction purposes. For JSON objects, the closest equivalent to a tag name would be the property name whose value is the object hash describing the model. This is fragile, and does not work if the response contains an array of models. ObjectQuery is a bit more general than name tags, but does not degenerate into XPath's complexity. The implementation is 182 lines of Objective C, including comments and whitespace.

Conclusion
JSON support does not stop at the parser. The toolkit fully embraces JSON, which is now available for initializing ModelSupport models. The toolkit's new Object Query bridges the gap between XML-based and JSON-based Web Services, and preserves API consistency in WebSupport.

Thank you reading this post! I'm looking forward to receiving your feedback or (even better) pull requests for ZergSupport.