GCMEncryption

The IdP now defaults to the use of a modern data encryption algorithm family called AES-GCM to encrypt XML. Earlier versions dating back to V2.0 relied on an older variant called AES-CBC. This page outlines the reason for this change, the process of algorithm selection in the software, and (for those so inclined) how to accomplish a controlled migraton to AES-GCM for Shibboleth SPs and the very small number of other implementations that support it.

Background

SAML supports message-level encryption of XML at a few different layers, the most common being to encrypt the entire Assertion issued to an SP so that it travels through the browser confidentially. In a few cases this might be valuable to hide information from the actual subject, but more often it's done to protect against malware in the client.

Unfortunately, the original XML Encryption standard only defined, practically speaking, a single family of data encryption algorithms (AES-CBC), and this is the only algorithm implemented with any consistency even today. CBC-mode has a long history of attacks, and XML Encryption proved vulnerable to them in a paper published in 2011. The attacks make it practical in some cases for the data to be decrypted by an attacker. The only true mitigation for this attack is if the Assertion is left unsigned prior to encryption and the Response is signed. This is why this is also the default behavior of our software and the best practice in SAML, though it should have been the absolutely-required approach.

It took some time for the XML Encryption standard to be updated with a newer option called AES-GCM, which is an example of what's known as "authenticated encryption", in which it becomes impossible to manipulate the ciphertext without detection prior to any attempt to decrypt the data. This is effectively a "built in" response signature which doesn't require active enforcement by a SAML SP. It took even more years for AES-GCM to appear in important libraries in a usable form, and it remains virtually unsupported at any scale today outside of the Shibboleth Project.

Despite that lack of support, we concluded that we could not in good conscience continue to ship an insecure default, so have made the decision to alter the default for new deployments to use the only secure option available.

Algorithm Selection

So why does the "default" matter and how does this impact the system?

When SAML was standardized, it defined no way of determining what signature or encryption algorithms a peer supported, in keeping with a very commercially-driven and impractical focus on manually interoperating pairs of systems one at a time with no thought of change or future evolution. As a result, IdPs and SPs make decisions about how to sign or encrypt with no information other than what they themselves can support.

The default, therefore, matters a great deal since it is, the majority of the time, the only input to the decision.

The Shibboleth Project, being neither commercial nor impractical, realized this was stupid very early on, and we defined a standard extension to SAML Metadata to allow IdPs and SPs to advertise the algorithms supported, and implemented support for that in our software. This is automatic and doesn't require any work by the receiving system, but of course the source of the metadata has a much bigger job to do in collecting or accurately capturing that information. Most deployers are hard-pressed to do this, and the information may be incomplete, fall out of date, etc.

As a result, there has been a lack of significant use of this extension and most of the time the default continues to be the only thing that matters.

With respect to the Shibboleth IdP, the process of laying out defaults for signing and encryption relies on a relatively ugly Spring XML bean definition, but a set of beans with different pre-defined defaults exist and can be selected using simple properties.

One of these properties, idp.encryption.config, is now explicitly defined to be "shibboleth.EncryptionConfiguration.GCM". The internal wiring continues to use AES-CBC as a default to prevent properly upgraded systems from any changes to their behavior.

Deployer Impact

Simply put, out of the box, your IdP is going to generate encrypted Assertions that a large percentage of non-Shibboleth SPs are going to be unable to decrypt, resulting a wide variety of failures and error messages. Some old Shibboleth SPs or software running on old Operating Systems will also fail to work, but bluntly, they're probably insecure to begin with.

If you don't care about the security of the encryption or simply don't have the will to do anything about it, then the quickest solution is to comment out the property, restart, and revert to previous behavior.

If you want to do something about this mess, then you're not going to have any choice but to attack the problem manually in a piecemeal fashion. You have two basic choices:

  • Leave the default set, and carve out exceptions for each SP that doesn't support GCM.

  • Change the default back to CBC, and carve out exceptions for each SP that supports GCM.

In both cases, knowing what something supports is largely a matter of guesswork and testing, though as a general heuristic, most Shibboleth SPs (usually recognizeable via entityID and by the /Shibboleth.sso paths in their endpoints) support GCM and most other SPs do not.

In either case, the most practical way to apply exceptions to the default is via the use of the Algorithm Metadata Filter, to attach the standard extension to an SP's metadata to denote it as supporting one or the other algorithm. Essentially you're using the filter to specify a different default algorithm for that SP.

The documentation of the filter includes a couple of useful examples that provide suggested approaches for gradually adopting the use of GCM while maintaining the default in place. Similar approaches would apply in the event that the default were changed back but migration were to be attempted by applying GCM via filter to selected SPs.

In effect, while it may be eminently practical to use CBC as the default and move gradually, we felt that changing the default going forward was the only effective means of raising the visibility of the issue.

Progress by Other Implementations

The decision to make this change has spurred some discussion by other projects to finally get GCM supported, which is good news. Other projects are welcome to add information here to assist with tracking.

PySAML2

https://github.com/IdentityPython/pysaml2/issues/671