Banned Crypto and the SDL

The SDL does not focus solely on issues such as buffer overruns, SQL injection and cross-site scripting issues; an important component is making sure developers use the correct cryptographic functionality. The reason for using the correct crypto and using crypto correctly is three-fold; first, cryptography offers many low-level building blocks, such as hash functions, symmetric encryption algorithms and message authentication codes, and it’s important to understand the strengths and weaknesses of each building block. Second, it’s easy to make subtle mistakes that render an application or the data it is protecting vulnerable. Finally, it’s important that the cryptographic building block provides adequate protection.

There are three broad buckets for SDL crypto compliance. The first is “don’t use banned crypto.” This is a little like “don’t use banned APIs” but for crypto rather than C or C++.The second is “use appropriate key lengths” and finally, generating random numbers.

Also note that Federal Information Standard 140 – Security Requirements for Cryptographic Modules (FIPS-140) compliance is not an SDL requirement, but for some teams within Microsoft it is a requirement.

Don’t use banned crypto

This is probably the most important requirement, and also the hardest to achieve in legacy code because many Internet protocols use older cryptographic primitives, and simply replacing an old and insecure algorithm with a newer one will lead to compatibility issues.

Examples here include MD4, MD5 and SHA-1. MD4 and MD5 are no-brainers because it’s easy to get hash collisions. One property of a good hash function is that it should be very difficult to find two or more documents that share the same hash. Real hash collisions were found in by Wang et al in 2004 in MD5, and in 2005 real PostScript documents were created that had the same hash. This led Ron Rivest, the cryptographer behind MD4 and MD5 to state that MD5 (and SHA-1) are ‘clearly broken.’ Because we’re starting to see real cracks in SHA-1, we believe that SHA-1 will be broken with the next ten-or-so years, so we decided to ban the use of SHA-1 in new code also.

Removing broken algorithms from existing code is often hard to do, so teams must remove banned crypto over time.

Theoretical weaknesses are one thing, but when theory becomes practical, well that’s a whole ‘nother ball game!

It’s all very well claiming that something is broken, but in the SDL we also tell engineers what they must do. So, instead of using MD4, MD5 and SHA-1, engineers should use SHA-256, SHA-384 or SHA-512. We’re keeping our eye on developments, as there’s a great deal of research going into hash functions now.

Next are symmetric ciphers. This boils down to “Use AES” and that’s pretty much all there is to say! DES and 3DES have small keys, 56-bit and 112-bit respectively, although 3DES does have a 168-bit keying option; however it too is too weak because of an attack called a “meet in the middle” attack, which renders the effective keysize to only 112-bits.

You must also use an approved cipher mode. We require Cipher Block Chaining (CBC) for most cases.

For asymmetric cryptography, RSA with 2048 modulus is required. There is a great deal of ongoing research attacking RSA so we will keep a close eye on events as they unfold. Elliptic Curve is also allowed; and there has been some interesting EC research lately.

The Mysterious Case of RC4

I’ve been asked many times why we have banned the use of RC4, even if a developer decides to use a zillion-bit key. The reason is because it’s regularly used incorrectly. So I’ll give a short version of the story.

· RC4 is a stream cipher; it encrypts and decrypts one byte at a time.

· RC4 is basically a pseudo-random number generator, and the key is the seed.

· RC4 encrypts by XORing the plaintext with the keystream (the random numbers)

· RC4 decrypts by XORing the ciphertext with the keystream.

· If two sets of plaintext (p1 and p2) of length len1 and len2 are encrypted with the same key, an attacker can XOR the two ciphertexts (c1 and c2) to yield the XOR of the two plaintexts up to length min(len1, len2). Analysis of (p1 XOR p2) is much easier than analyzing c1 or c2. Mason et al wrote an interesting paper on the subject.

· Because RC4 is a stream cipher, it’s possible for an attacker to ‘flip a bit’ in a controlled manner without the recipient knowing that the bit had been manipulated. Hence you should always have some form of message integrity check. Of course, even a block cipher should have some form of integrity check too, but the issue is exacerbated when using RC4.

Have you ever noticed that there is no RC4 implementation in the .NET Framework!? David LeBlanc has a great write-up on various crypto issues in Microsoft Office, specifically pointing out RC4 issues.

Two years ago I wrote a very simple tool that runs as a Visual Studio macro to help find banned crypto in your code. You can find the code here.

Use appropriate key lengths

I already touched on this, but for symmetric ciphers you must use 128-bit or longer keys and for RSA you must use 2048-bit modulus. For Elliptic Curve Suite B crypto, we require a minimum of 256-bit keys, and ECC-based key exchange and digital signatures must use one of the three NIST approved curves (P-256, P-384, or P521).

The reason for these sizes is because as computers gain power, the cost for attacking a given key-space become less prohibitive. We’re now seeing software that harnesses the enormous computing power of graphic cards from companies like NVIDIA and ATI used to attack keys and guess passwords.

Generating Random Numbers

Good crypto requires high-entropy random number generation; we’re very specific in the SDL about what’s required. Call either:

· CryptGenRandom

· BCryptGenRandom

· System.Security.Cryptography.RNGCryptoServiceProvider

That’s all there is to it!

I have left one thing out, which we will discuss another day, and that’s the topic of crypto-agility. crypto-agility is the ability to swap out crypto-algorithm support quickly from within an application without having to update and recompile the application. But in short, please do not hard code crypto algorithms into your code, read the algorithms from an adequately protected configuration file or from the protected document as metadata.

Cryptographic Exceptions (no, not the try/catch variety!)

Invariably there are exceptions that must be dealt with; for example you might need to use SHA-1 as part of a key derivation function owing to backward compatibility, or an IETF document might require you to use 3DES for symmetric encryption or DSA rather than RSA for signatures. At Microsoft, all crypto-related exceptions must go through the “Crypto Board” for sign off (or push back.) The board is staffed by about a dozen cryptographers and about a dozen interested parties, me included.

A good example of the exception process in action is to allow or deny the use of a hash function beyond its ‘classic’ hashing capability. Hash functions can be used for:

· Non-cryptographic checksums (a more collision resistant CRC)

· Hash table lookup

· Key derivation from low-entropy passwords

· Digital Signatures

· Message authentication codes

Clearly the bar for a digital signature is far higher than for using a hash as a CRC-replacement.

Having the crypto board in the system helps us reduce the chance that engineering groups will use cryptography inappropriately, and is another great example of how the primary SDL focus is preventing design and code bugs from entering the code in the first place.

About the Author
Michael Howard

Principal Security Program Manager

Michael Howard is a principal security program manager on the Trustworthy Computing (TwC) Security team at Microsoft, where he is responsible for managing secure design, programming, and testing techniques across the company. Michael is an architect of the Security Development Read more »