Composer Dependency Changed PR-staging

Pending

User tests: Successful: Unsuccessful:

avatar mbabker
mbabker
18 Jun 2017

Pull Request for Issue #13568

Summary of Changes

PHP 7.2 will be removing ext/mcrypt from the core distribution and ext/sodium will be added to core as a new encryption library. As the JCryptCipher classes are primarily built around mcrypt (and inherently what is present in PHP core), we should add support for the new library as well.

ext/sodium isn't restricted to PHP 7.2 installations only. There is also a PECL extension providing support for PHP 5.4 through 7.1 and the sodium_compat polyfill providing support down to PHP 5.2.4. The polyfill is included in this PR to make things usable for all of our supported environments, and the polyfill already has logic in place to support working with either the native PHP API or the PECL extension, so we can just arbitrarily call into the polyfill API without doing extra work on our own.

Testing Instructions

The unit test coverage for the class best demonstrates its use:

$cipher = new JCryptCipherSodium;
$key    = $cipher->generateKey();
$data   = 'My encrypted data.';

$cipher->setNonce(\Sodium\randombytes_buf(\Sodium\CRYPTO_BOX_NONCEBYTES));

$encrypted = $cipher->encrypt($data, $key);
$decrypted = $cipher->decrypt($encrypted, $key);

if ($decrypted !== $data)
{
	throw new RuntimeException('The data was not decrypted correctly.');
}

One thing to note here. Unlike our other ciphers, a nonce must be set and used for both the encryption and decryption of data, and must be the same value on both ends of the process. Otherwise, this is no different than the existing API.

Documentation Changes Required

Document the added class and its use.

//cc @joomla/security

avatar mbabker mbabker - open - 18 Jun 2017
avatar mbabker mbabker - change - 18 Jun 2017
Status New Pending
avatar joomla-cms-bot joomla-cms-bot - change - 18 Jun 2017
Category Repository External Library Libraries
avatar SniperSister
SniperSister - comment - 19 Jun 2017

As far as I know, sodium_compat still did not had the cryptographic review that the author was strongly asking for, right? If yes, is it wise to build our crypto stuff around it?

avatar wilsonge
wilsonge - comment - 19 Jun 2017

It has not (it's in the readme Michael linked to). I'm also unsure (but not strongly against) on whether we just require min php 7.2 in the is_supported.

We do have to be very careful about documenting that clearly as a minimum in php doc blocks etc

avatar mbabker
mbabker - comment - 19 Jun 2017

I would not lock it to only PHP 7.2 since as noted there is a PECL extension offering support down to PHP 5.4 and is the predecessor for the core API that will be in 7.2. So depending on your server config, the polyfill is the only way to get support for PHP 5.3 and covers the other PHP branches if you can't install the PECL extension. We do have other system components which require PECL extensions that aren't part of the core PHP distro (Memcached and Redis for cache/session support) or depend on PEAR packages (Cache_Lite), so it's not unprecedented for us to have API components with extra dependencies.

Not using the polyfill though complicates this implementation quite a bit. Two main issues come to mind. First, there would be no way to support PHP 5.3 at all (in many ways that's fair, it's a dead branch anyway, but it is part of our supported version range and thus far we don't have features in core that are only available on newer PHP versions). Second, the API between PECL and core PHP 7.2 is different (PECL uses a namespaced API whereas to put the code in core everything had to move to core PHP's naming convention), so we'd have a lot of conditionals in the class for each of the functions we're using.

avatar paragonie-scott
paragonie-scott - comment - 12 Jul 2017

Second, the API between PECL and core PHP 7.2 is different (PECL uses a namespaced API whereas to put the code in core everything had to move to core PHP's naming convention), so we'd have a lot of conditionals in the class for each of the functions we're using.

Just adding sodium_compat actually nullifies that. If you're on < 7.2, it maps sodium_* to \Sodium\*. If you're on 7.2+, it will do the converse. If you want to simplify debugging paths, just use \ParagonIE_Sodium_Compat::* and it will automatically use the C extension where it can, and polyfill the rest.

avatar paragonie-scott
paragonie-scott - comment - 24 Jul 2017

@SniperSister

If yes, is it wise to build our crypto stuff around it?

First, let's assume there's some vulnerability in sodium_compat. What might it look like?

Let's begin with the attacks that have been eliminated by its design (which is enforced via unit tests and static analysis):

  • It won't be a straightforward cryptanalysis break, since:
    • For shared-key encryption, we're implementing one of the eSTREAM finalists which has been hit hard by cryptographers for years and still has a higher security margin than AES.
    • For shared-key authentication, we're using PHP's built-in HMAC.
    • For public-key cryptography, we're using Curve25519.
    • If any of the above turns out to be false, the problem isn't with sodium_compat, but with all modern cryptography.
  • It won't be a protocol construction flaw, since:
    • For shared-key encryption, we always Encrypt Then Authenticate.
    • For shared-key authentication, we're using hash_equals() to prevent timing side-channels.
    • For public-key encryption (ECDH over Curve25519 then shared-key encryption), we're using a Montgomery ladder construction which only sends the X coordinate. This eliminates invalid curve attacks and timing side-channels.
    • For public-key digital signatures, Ed25519 is a deterministic signature scheme, which prevents a private-key leaking security flaw.
  • It won't be any of the obvious cache-timing side channels in PHP, including chr().
  • It won't be any of the less-obvious (and maybe not exploitable) side-channels, including:

There is still some attack surface that sodium_compat does not, and cannot, address:

  • Zeroing memory buffers is impossible from PHP.
  • Some extensions and features, such as OpCache, might now or in the future introduce premature optimizations that include an accidental side-channel
  • If there is a vulnerability in PHP itself, that causes a side-channel leak, we probably cannot prevent it

That's the crux of what the audit scope was meant to address: Is it possible to implement completely constant-time cryptography in PHP without just writing it in C as an extension?

Even if the answer is "No", in practical terms, you really only need to worry about local attackers (e.g. neighbors in cloud hosting) that can do attacks on the processor's caches (e.g. FLUSH+RELOAD). If you have a high security requirement where this exposure to an unproven hypothetical risk is not acceptable, it's easily mitigated by the following command:

pecl install libsodium

Whether or not it's wise to use sodium_compat is really your decision, but with this knowledge in hand, I hope whatever answer you go with is a lot clearer.

avatar SniperSister
SniperSister - comment - 24 Jul 2017

@paragonie-scott thanks a lot for the detailed explanation, that was really helpful!

@mbabker based on the feedback, I'm fine with using the polyfill.

avatar zero-24 zero-24 - test_item - 24 Jul 2017 - Tested successfully
avatar zero-24
zero-24 - comment - 24 Jul 2017

I have tested this item successfully on b11ee6f

Works for me with the given test Instructions. Thanks!


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/16754.

avatar joomla-cms-bot joomla-cms-bot - change - 25 Jul 2017
Category Repository External Library Libraries Repository External Library Composer Change Libraries
avatar rdeutz rdeutz - change - 26 Jul 2017
Status Pending Fixed in Code Base
Closed_Date 0000-00-00 00:00:00 2017-07-26 05:15:38
Closed_By rdeutz
Labels Added: PR-staging
Removed: ?
avatar rdeutz rdeutz - close - 26 Jul 2017
avatar rdeutz rdeutz - merge - 26 Jul 2017

Add a Comment

Login with GitHub to post a comment