A bit of history…
Mono has always provided fully managed implementations of almost every cryptographic algorithms supported by .NET, either directly (in the base class libraries) or indirectly (e.g. additional algorithms required for X.509 or SSL/TLS support).
That approach gets you full cryptographic support everywhere the Mono JIT/runtime itself works, which covers a pretty large spectrum, with no external dependency required.
Now this was not always the best choice for performance but it did not matter much since .NET (and Mono) crypto stack is meant to be extendable and replaceable thru CryptoConfig. E.g. you can find some faster alternatives inside Crimson using libmhash or
Back to MonoTouch…
Things in iOS-land are a bit different. Extensibility does not work as well because of the platform restrictions MonoTouch must abide to. The mono runtime and the class libraries are not shared (each application get its own) often tailored (by both linkers) copies. Not to mention you cannot share code between applications or even load code dynamically. That effectively kills all the benefits that
CryptoConfig can provide.
OTOH the lack of control, as a owner, over the device’s operating system means we, as developers, know what’s in there. In this case we can be sure that CommonCrypto is always present. It’s an external dependency but not an optional or additional dependency.
Since we can’t offer extensibility we need to choose what’s offered. In MonoTouch 5.2 (and earlier) that was the managed implementations. For the upcoming MonoTouch 5.4 (starting now with 5.3.3 alpha) this will be CommonCrypto-based implementations.
Why ? Switching has three benefits:
1. Likely incoming FIPS 140 certification
Thanks to NIST it’s no secret (pdf) that Apple is been seeking FIPS 140 certifications for CommonCrypto on iOS. This can be a long process but intermediate results, like AES validations, can already be found online.
It does not mean much today (in progress == no certification) but it could become crucial for some applications, if you want to sell them to either the US or Canadian federal government, in the future. Whenever it happens you’ll be ready, not waiting, for this 🙂
2. Smaller application size
Inside .NET assemblies p/invoke declarations are methods without any body (no IL, just metadata). As such they tend to be small – much smaller than the cryptographic code they replace (even with the additional glue code needed).
This means that by using
CommonCrypto we can reduce the size of
mscorlib.dll (-19.5 KB),
System.Core.dll (-12 KB) and
Mono.Security.dll (-2 KB). Also the internal calls required for the pseudo random number generator (PRNG) can be eliminated by the native linker.
As a result my benchmarking application, fully linked and compiled using LLVM for ARMv7 (Release), is 99.5KB smaller than before. That does not include the effects of the other features added in MonoTouch 5.3 – with all the other enhancements the size, when compared to 5.2.11, is 219 kb smaller.
3. Better performance
Even if it’s not hard to find counterexamples native code generally outperforms managed code. That’s often the case for cryptographic code that is optimized or, in some cases, hardware accelerated (recent iOS devices offer this for SHA1 and AES in CBC mode).
For MonoTouch (or Mono in general) this is true when the buffer size are large enough that the managed/native transition cost can be hidden by the faster code. With an optimal buffer size I get the following results when comparing benchmarks on the existing managed code (5.2.11) versus the new CommonCrypto-based code (5.3.3).
The vertical scale represents the improvement factor, i.e. Managed is 1x. Now forget about the high end (AES) numbers that changes the scale of the graphic. I’ll share the exact incantations and sacrifices required, in a future post, but you’re not likely to get them (or even half of them) in real life conditions. Part of it is because benchmarks are lies and a funny fact makes this one an even bigger liar than usual.
Still those are impressive gains that requires nothing but recompiling your application with MonoTouch 5.3.3 (or later). Technical details about what changed and more graphics to follow…