# [RFC] OpenSSL AEAD support

- Thread: https://externals.io/message/90194
- Original archive: https://news-web.php.net/php.internals/90194
- Started by Jakub Zelenka on 2016-01-06T15:01:30+00:00
- Messages: 8
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #90194 — Jakub Zelenka — 2016-01-06T15:01:30+00:00

URL: https://externals.io/message/90194#90194

Hi,

I would like to propose an addition to the openssl ext - extending
openssl_encrypt and openssl_decrypt to support AEAD (Authenticated
Encryption with Additional Data - GCM and CCM modes support). There was
some discussion in past and people have been asking about that for some
time so I finally finished the implementation (it's more or less rewrite of
both functions) and created this RFC to discuss all concerns if there are
any...

https://wiki.php.net/rfc/openssl_aead

Cheers

Jakub

---

## #90196 — Bishop Bettini — 2016-01-06T15:35:09+00:00

URL: https://externals.io/message/90194#90196 · In reply to: #90194

Hi Jakub,



> Hi,
>
> I would like to propose an addition to the openssl ext - extending
> openssl_encrypt and openssl_decrypt to support AEAD (Authenticated
> Encryption with Additional Data - GCM and CCM modes support). There was
> some discussion in past and people have been asking about that for some
> time so I finally finished the implementation (it's more or less rewrite of
> both functions) and created this RFC to discuss all concerns if there are
> any...
>
> https://wiki.php.net/rfc/openssl_aead


I think the API might need to be more generic so that any future cipher
modes with different parameters could also be passed in.

The reference model I'd suggest is the "context" parameter passed to stream
related-functions.  Userland creates a context, then passes the context to
the encrypt/decrypt functions. The context is specific to the wrapper and
drives specific behavior. Encrypt can add to the context any specific
cipher state that needs to be passed along to decrypt.

Using this model, the openssl API might look like:

$context = openssl_context_create([ 'aead' => [ 'aad' => '...',
'tag_length' => '...' ]]);
$ciphertext = openssl_encrypt(
    $data, $method, $password, $options, $iv,
    $context // here is the new parameter, encapsulating all cipher
specifics
);

echo $context['aead']['tag']; // populated by openssl_encrypt

$plaintext = openssl_decrypt(
    $ciphertext, $method, $password, $options, $iv,
    $context // fully-reversible, because all necessary data are in context
);

Might also want to check in with Scott Arciszewski (copied), as he's
working on a new crypto API <https://github.com/paragonie/pco_prototype>
 proposal.

Cheers,
bishop

---

## #90199 — Jakub Zelenka — 2016-01-06T16:09:10+00:00

URL: https://externals.io/message/90194#90199 · In reply to: #90196

Hi,



> Hi Jakub,
>
> 
> > […]
>
>
> I think the API might need to be more generic so that any future cipher
> modes with different parameters could also be passed in.
>
> The reference model I'd suggest is the "context" parameter passed to
> stream related-functions.  Userland creates a context, then passes the
> context to the encrypt/decrypt functions. The context is specific to the
> wrapper and drives specific behavior. Encrypt can add to the context any
> specific cipher state that needs to be passed along to decrypt.
>
> Using this model, the openssl API might look like:
>
> $context = openssl_context_create([ 'aead' => [ 'aad' => '...',
> 'tag_length' => '...' ]]);
> $ciphertext = openssl_encrypt(
>     $data, $method, $password, $options, $iv,
>     $context // here is the new parameter, encapsulating all cipher
> specifics
> );
>
> echo $context['aead']['tag']; // populated by openssl_encrypt
>
> $plaintext = openssl_decrypt(
>     $ciphertext, $method, $password, $options, $iv,
>     $context // fully-reversible, because all necessary data are in context
> );
>
>
Please see note in https://wiki.php.net/rfc/openssl_aead#rejected_features
. Any context related features will add a lot to the size of the
implementation. In this case it would also mean introducing an object with
dimension handler to the openssl ext which doesn't really match with the
rest of the extension API. The proposed API is more conformant to the rest
and the code addition is also limited which is very important from the
maintenance point of view.

I have got already an extension where you can do all of this context
related stuff ( see https://github.com/bukka/php-crypto ) but I don't think
that anything like this should be part of the openssl ext. I think we
should concentrate on adding just the most important features with minimal
code addition to openssl ext and also concentrate on the fixing the actual
bugs. Bare in mind that all of this has to be maintained for very long time
and when you look to the regular contributors to openssl ext, you won't see
too many people...

To sum it up this is a minimal proposal to add AEAD support to openssl ext.
Anything context related is out of scope of this RFC.

Cheers

Jakub

---

## #90200 — Albert Casademont — 2016-01-06T16:17:36+00:00

URL: https://externals.io/message/90194#90200 · In reply to: #90199

+1 thanks Jakub!



> Hi,
>
> 
>
> > […]
> context
> > […]
> Please see note in https://wiki.php.net/rfc/openssl_aead#rejected_features
> . Any context related features will add a lot to the size of the
> implementation. In this case it would also mean introducing an object with
> dimension handler to the openssl ext which doesn't really match with the
> rest of the extension API. The proposed API is more conformant to the rest
> and the code addition is also limited which is very important from the
> maintenance point of view.
>
> I have got already an extension where you can do all of this context
> related stuff ( see https://github.com/bukka/php-crypto ) but I don't
> think
> that anything like this should be part of the openssl ext. I think we
> should concentrate on adding just the most important features with minimal
> code addition to openssl ext and also concentrate on the fixing the actual
> bugs. Bare in mind that all of this has to be maintained for very long time
> and when you look to the regular contributors to openssl ext, you won't see
> too many people...
>
> To sum it up this is a minimal proposal to add AEAD support to openssl ext.
> Anything context related is out of scope of this RFC.
>
> Cheers
>
> Jakub

---

## #90219 — Bishop Bettini — 2016-01-06T19:28:08+00:00

URL: https://externals.io/message/90194#90219 · In reply to: #90199

> Hi,
>
> 
>
> > […]
> https://wiki.php.net/rfc/openssl_aead#rejected_features . Any context
> related features will add a lot to the size of the implementation. In this
> case it would also mean introducing an object with dimension handler to the
> openssl ext which doesn't really match with the rest of the extension API.
> The proposed API is more conformant to the rest and the code addition is
> also limited which is very important from the maintenance point of view.
>

Ok, a context resource may not be pragmatic. Perhaps a compromise in the
form of a thin wrapper:

string openssl_encrypt_aead(string $data , string $method , string
$password [, int $options = 0 [, string $iv = "" [, string &$tag = "" [,
string $aad = "" [, int $tag_length = 16 ]]]])

string openssl_decrypt_aead(string $data , string $method , string
$password [, int $options = 0 [, string $iv = "" [, string $tag = "" [,
string $aad = "" ]]]] )

This actually feels more right anyway: openssl_encrypt only does
encryption, whereas openssl_encrypt_aead does encryption *and* integrity.
I would hate for users to pass a method of aes128 and think they can forgo
an HMAC because they thought PHP would give them back a valid tag.

---

## #90228 — Jakub Zelenka — 2016-01-06T19:59:50+00:00

URL: https://externals.io/message/90194#90228 · In reply to: #90219

> 
>
> > […]
>
> Ok, a context resource may not be pragmatic. Perhaps a compromise in the
> form of a thin wrapper:
>
> string openssl_encrypt_aead(string $data , string $method , string
> $password [, int $options = 0 [, string $iv = "" [, string &$tag = "" [,
> string $aad = "" [, int $tag_length = 16 ]]]])
>
> string openssl_decrypt_aead(string $data , string $method , string
> $password [, int $options = 0 [, string $iv = "" [, string $tag = "" [,
> string $aad = "" ]]]] )
>
> This actually feels more right anyway: openssl_encrypt only does
> encryption, whereas openssl_encrypt_aead does encryption *and*
> integrity.  I would hate for users to pass a method of aes128 and think
> they can forgo an HMAC because they thought PHP would give them back a
> valid tag.
>

This is a good point. I would probably go with a bit different and maybe
simpler solution. How about emitting notice when $tag param is supplied for
non aead mode?

Thanks for the feedback!

Jakub

---

## #90240 — Bishop Bettini — 2016-01-06T21:32:17+00:00

URL: https://externals.io/message/90194#90240 · In reply to: #90228

> 
>
> > […]
>
> This is a good point. I would probably go with a bit different and maybe
> simpler solution. How about emitting notice when $tag param is supplied for
> non aead mode?
>

I think the need for a message highlights an API design problem, and I'd
rather eliminate the need with a purpose-built API.

Still, AEAD is a valuable addition to the API.  Thanks for submitting the
RFC!

---

## #90350 — Jakub Zelenka — 2016-01-08T14:06:58+00:00

URL: https://externals.io/message/90194#90350 · In reply to: #90240

> 
>
> > […]
>
> I think the need for a message highlights an API design problem, and I'd
> rather eliminate the need with a purpose-built API.
>
>
I have been thinking about it and I don't think we need to add special
functions that would work just for cipher algs ($method) with  AEAD modes.
The logic and other parameters are the same. The only difference is
supplying the tag. We could compare it to the ciphers modes with IV that
requires an $iv parameter. Then a notice is triggered if IV is not supplied
as well as a notice is triggered if you supply IV for ECB mode. I know that
this is not the same but the notices are already used in this way so I
think that this is a more conforming way.

This should be of course documented. There should be definitely a note that
a tag will be provided only for GCM and CCM modes. It means only for
following methods:

aes-128-gcm
aes-192-gcm
aes-256-gcm
aes-128-ccm
aes-192-ccm
aes-256-ccm

and their upper case aliases of course...

I will update the patch and RFC accordingly.

Thanks for the feedback!

Jakub
