One of the benefits of being a Microsoft Security MVP is seeing the most interesting environments to build secure systems and applications. One day I will be talking to someone about command and control systems for critical armaments, and the next day I will be talking with someone who is building a website that takes credit card information in a storefront. Across any system of complexity, when it comes to cryptography there is a lack of a good understanding of how to use it effectively. I am of course generalizing here, as there are plenty of developers that have learned to write secure code. However, I will often come across systems where people misuse cryptography. Or worse yet, roll their own! I won’t get on a soapbox and tell you why that is a really bad idea, but will instead tell you to go pick up a good book like Applied Cryptography from my friend Bruce Schneier.
In discussions about this lack of knowledge with some of my friends like John Bristowe in Developer & Platform Evangelism (DPE) at Microsoft, it was clear that instead of complaining about the problem, I should do something about it. Hence, this post. What is to follow is a practical view on how you can apply cryptography in a way to meet requirements with FIPS, a US government computer security standard, that trips up many .NET developers when they first try to use the built in cryptographic classes with managed code.
For those who don’t know, let’s start off with defining what FIPS is and how it may affect you. FIPS stands for the Federal Information Processing Standard, which is basically a standard to accredit cryptographic modules. It is the standard which the National Institute of Standards and Technology (NIST) oversees for the security specific criteria in which cryptographic modules – both private and open source – must adhere to meet requirements for use in US government and other regulated bodies (i.e. health care and financial institutions) for use to collect, store, transfer and share sensitive but unclassified (SBU) data. It just so happens to be the bar by which most other government and industry bodies follow, including many here in Canada. You can learn more about FIPS by checking out the Computer Security Division website over at NIST.
FIPS is interesting because to meet government requirements, Microsoft has included configuration settings and code libraries to allow developers to meet the strict requirements of these guidelines. However, it is VERY common to see developers get stuck when building applications using the .NET Framework because this isn’t documented or defined well. A good example of this is the (mis)use of AES symmetric-key encryption to meet FIPS requirements. Let me explain why.
First, a little history of AES for those that don’t know much about cryptography. AES stands for the Advanced Encryption Standard and is a replacement for its predecessor, DES or Data Encryption Standard. AES comes in three-block ciphers: AES-128, AES-192 and AES-256. The actual cryptographic algorithm selected for AES is called the Rijndael (pronounced rain-dal) cipher, which was selected after an exhaustive analysis. It actually took over five years through a standardization process in which 15 competing designs were presented and evaluated before Rijndael was selected. There isn’t enough alcohol on this planet to have my brain test such complexity. That’s why they are the crypto-geeks; let’s live vicariously through their expertise, shall we?
To bring this full circle, in the .NET Framework you will find that in the System.Security.Cryptography library there exists a class called RijndaelManaged. Since the NIST selected this for AES, this is all we need to meet FIPS requirements for our crypto, right? Wrong. It is quite easy (and common) to misuse this class library and end up NOT meeting the requirements as defined by NIST. And here’s why.
Remember how I mentioned that AES officially supports three block ciphers? Well, it gets a bit more complicated than that. AES also only supports the use of 128-bit block size for the cipher. Herein lies the problem. In the .NET framework, RijndaelManaged can accept key sizes of 128, 160, 192, 224 and 256 bits respectively. Furthermore, the block size can be 128, 192, or 256 bits. It is quite easy to actually use the RijndaelManaged class and NOT be compatible with a different system that speaks AES. And, it gets even worse. If you use a cipher mode of operation that adjusts the block size, it will BREAK compatibility. One such example is use of the cipher feedback mode (CFB) which will adjust the feedback block size on you. So even if you were careful to use a valid block cipher and set the block size to 128, it could be possible for the CFB to alter it on you. The result… again you fall out of compliance. Don’t you just love all this intricacy that isn’t well documented? *sigh*
OK, so enough with the doom and gloom. Here is the first tip if you want to make RijndaelManaged be compatible with FIPS: ALWAYS use a block size of 128 bits and don’t use an op mode of CFB, if you can. Instead, use cipher block chaining (CBC). If you must use CFB, ensure it ALWAYS uses a feedback block of 128 bits.
Why is this important? Well, in all honestly there is a little dirty secret no one likes to talk about. Back then Microsoft apparently didn’t actually certify RijndaelManaged. And if you scour the Internet, you will find lots of articles and posts over the years where people give differing advice on how to handle cryptography in managed code, many of them slightly (or massively) incorrect. Especially if they use weaker hash algorithms like MD5. In the .NET 2.0 era it has been common for software vendors to bypass security policy that may be trying to enforce FIPS compliant algorithms. It’s actually a Microsoft supported configuration switch. Basically, you just need to tell the CLR to ignore it.
<configuration> <runtime> <enforceFIPSPolicy enabled="false"/> </runtime> </configuration>
Now, I don’t recommend you do this. Actually, I frown on it. If a server has been explicitly configured to enforce FIPS compliant algorithms, who are you to reduce the security effectiveness of the system? Fix your code! Do it right. Don’t be lazy. (We’ll come back to talk about how to do that in a moment.) Or don’t try selling to industries that would enforce this policy. 😉
OK, so since we are talking about the security policy for FIPS, how can you tell if its actually enabled? That’s an easy one. You will find that in the Windows security settings under the policy "System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing". Setting that ultimately impacts the registry key at HKLM\System\CurrentControlSet\Control\Lsa, modifying the DWORD FIPSAlgorithmPolicy value. A value of 1 means it’s enabled. And you can easily see the impact of this change in a simple bit of test code. Try something like this:
MD5 md5 = new MD5CryptoServiceProvider();
Console.WriteLine("MD5 algorithm created!");
If the security policy for FIPS is not enabled, you will see the string “MD5 algorithm created!” echoed to the console. if the policy is enabled, you will end up seeing an InvalidOperationException that spews the following error:
System.InvalidOperationException: This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms.
Interesting enough, Microsoft was smart enough to block creation in all known methods. So even if you tried to instantiate it indirectly using the different Create() methods, it would block you there too. Which is a good thing.
Now, before you go out and just start switching the bit on for all your systems, please understand that this policy settings has an impact to the rest of the system, not just your own .NET code. It actually affects a lot within Windows, including how SSL works in IE and IIS, how connections are established in RDS and even how EFS acts on the system. I highly recommend you check out knowledge base article 811833 on Microsoft’s support site for more information on how this may impact your systems. One glimmer of hope is that as the desktops and servers mature, building FIPS in has become more reliable in the newer generation of Windows Server 2008 and Windows 7. It is Windows Server 2003 and XP that you will find more incompatibility.
I promised I would give you guidance on how to fix your code. The answer isn’t in reconfiguring your app so the CLR ignores FIPS compliance checks. Or disable FIPS policy settings in the registry. Or writing your own cipher that won’t be checked by the setting *shudder*. The real answer is to use a FIPS compliant algorithm to begin with that HAS been certified! It does exist. You just need to be using the .NET 3.5 framework or newer to get access to it. That would be the CAPI wrapped AesCryptoServiceProvider class. Basically it ties into the operating system libraries which have been certified for FIPS. Another option would be to use the AesManaged class, which basically is a wrapper for RijndaelManaged but designed to prevent you from using wrong block sizes or using a CFB ops mode. It hasn’t been certified in the same vein, but it guarantees that you use Rijndael correctly for AES. Any way you look at it, its a MUCH better way to do it correctly.
I hope this brings some closure on what to think about when using managed code to meet FIPS compliance. Outside of our discuss of symmetric-key encryption with AES, you can apply the same logic for hashing algorithms too. Check out SHA512CryptoServiceProvider and SHA512Cng as examples. In the end, designing it right the first time is the way to go. If you are addressing legacy code running on platforms enforcing FIPS compliant algorithms, refactor it accordingly using the appropriate libraries and classes. Don’t mess with the attack surface of the system by altering security policy or forcing the CLR to ignore it. Spend the time to do it right; it’s much safer for everyone that way.
Hope you found this article useful. Feel free to leave a comment and let me know what you think!
About Dana Epp
Dana Epp, Microsoft Enterprise Security MVP, researches software security and sets the vision in the convergence of information security principles and practices with digital information asset protection for small business. As a computer security software architect, Mr. Epp has spent the last 15 years focusing on computer programming with a particular emphasis on security engineering to offer a safer computing environment for business. His latest research has been on risk-based authentication, focusing on strong two-factor authentication for small business.