Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] Remove unnecessary double MAC for AEAD ciphers #38475

Merged
merged 1 commit into from
Aug 20, 2021

Conversation

Krisell
Copy link
Contributor

@Krisell Krisell commented Aug 20, 2021

This PR does two things:

  1. It resolves a small bug in the generateKey method (wrong result for AES-128-GCM, see comment in code below).
  2. It removes the unnecessary hmac computation for AEAD ciphers, improving performance and reducing encrypted data amount.

These two problems were introduced recently when support for GCM ciphers was added, in #38190

GCM is a so called Authenticated Encryption scheme (AEAD), which means that a Message Authentication Code (mac) is included in the algorithm and handled by openssl_encrypt/openssl_decrypt. This is called tag in the code, and serves the exact same purpose as the mac that is also present from before (and necessary in the CBC-case, which is not natively authenticated).

This PR removes the HMAC computation in the GCM case, since the tag already ensures data integrity (before decryption is attempted). This simplifies the code (very important for cryptographic implementations), improves performance and reduces the amount of data stored/transmitted. As an example, the XSRF and session id cookies are reduced by around 25 % (but the reduction for larger data is of course much smaller).

The changes are backwards compatible with #38190, and of course with any data stored before that. In fact, the only change to the decryption part is skipping the MAC validation in the case of an AEAD-cipher being used.

This was actually all done correctly in a 2017 PR by bukka, #21963, but that was never merged. I did use that PR as inspiration for this, but I tried to keep the changes to a minimum to increase chances of merging. One larger change is generalizing the list of supported ciphers, and adding the AEAD support as a property. This should simplify the process of adding additional ciphers in the future, and simplified other parts of the code.

@@ -70,7 +82,7 @@ public static function supported($key, $cipher)
*/
public static function generateKey($cipher)
{
return random_bytes($cipher === 'AES-128-CBC' ? 16 : 32);
Copy link
Contributor Author

@Krisell Krisell Aug 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was incorrect for AES-128-GCM, causing key:generate to output a 256 bit key and the application to throw a RuntimeException.

@driesvints driesvints changed the title Remove unnecessary double MAC for AEAD ciphers [8.x] Remove unnecessary double MAC for AEAD ciphers Aug 20, 2021
{
return hash_hmac('sha256', $tag.$iv.$value, $this->key);
return hash_hmac('sha256', $iv.$value, $this->key);
Copy link
Contributor Author

@Krisell Krisell Aug 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the only change here and in validMac is reverting the unnecessary tag addition in https://github.com/laravel/framework/pull/38190/files

@Krisell Krisell force-pushed the encryption-aead-fixes branch 2 times, most recently from 2bd55ef to e60732f Compare August 20, 2021 11:55
@@ -184,7 +194,6 @@ public function decryptString($payload)
*
* @param string $iv
* @param mixed $value
* @param string $tag
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you re-add this?

@Krisell Krisell force-pushed the encryption-aead-fixes branch from e60732f to 8abf9c6 Compare August 20, 2021 12:25
@Krisell Krisell force-pushed the encryption-aead-fixes branch from 8abf9c6 to 3800323 Compare August 20, 2021 12:30
@Krisell
Copy link
Contributor Author

Krisell commented Aug 20, 2021

Removing the $tag parameter from the mac-functions is technically a breaking change for extending code (not for data, since tag is always the empty string for non-aead ciphers), however only in relation to the commit a few weeks back, and this was determined acceptable, see #38475 (comment)

@Krisell
Copy link
Contributor Author

Krisell commented Aug 20, 2021

Could the following be a problem?
Since the MAC is no longer included in the AEAD case with this PR (the whole point), downgrading Laravel after using this will cause session invalidation (since the unnecessary mac check will fail). I'm not sure how you usually consider BC for revertability? Of course, this would only affect applications already using the new GCM mode, so the window of risk is very small.

@driesvints
Copy link
Member

No I don't think that's a high risk.

@taylorotwell taylorotwell merged commit 3800323 into laravel:8.x Aug 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants