Skip to content

Add ext/sodium for PHP 7.2.0 #2560

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

Closed
wants to merge 1 commit into from

Conversation

paragonie-scott
Copy link
Contributor


PHP_SUBST(LIBSODIUM_SHARED_LIBADD)

PHP_NEW_EXTENSION(libsodium, libsodium.c, $ext_shared)
Copy link
Member

Choose a reason for hiding this comment

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

Already discussed, please, drop lib prefix, so only "sodium"

Copy link
Contributor Author

@paragonie-scott paragonie-scott Jun 6, 2017

Choose a reason for hiding this comment

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

Good point. @sgolemon suggested starting a PR just to get it in the door before June 15, then we'd make any changes afterwards, so I was just dumping it as-is. :P

AC_MSG_RESULT(found in $i)
fi
done
fi
Copy link
Member

Choose a reason for hiding this comment

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

Using pkg-config output would be better than searching in some hardcoded path

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure how to do that.

Copy link
Member

Choose a reason for hiding this comment

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

See some other ext for example (zip, interbase, ...)
Else I will take care of it.

@remicollet
Copy link
Member

Please drop EXPERIMENTAL as obviously no more experimental....

extern zend_module_entry libsodium_module_entry;
#define phpext_libsodium_ptr &libsodium_module_entry

#define PHP_LIBSODIUM_VERSION "2.0.0"
Copy link
Member

Choose a reason for hiding this comment

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

Do you want to keep it sync with pecl for older version ?
Else, could make sense to drop specific version (and use PHP version as for most of other extensions)

@@ -1,5 +1,5 @@
dnl $Id$
dnl config.m4 for extension libsodium
dnl config.m4 for extension sodium

PHP_ARG_WITH(libsodium, for libsodium support,
[ --with-libsodium[[=DIR]] Include libsodium support])
Copy link
Member

Choose a reason for hiding this comment

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

I think we need 2 options

  • one for the ext (--enable-sodium)
  • one optional to set the library directory (--with-libsodium=DIR)

And for consistency all "libsodium" fonction (minit, minfo, ...) should also be renamed

Copy link
Member

Choose a reason for hiding this comment

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

I don't think there should be --enable-sodium as it depends on the library. From what I know, enable is just for extensions without lib dependency and for lib dependency we always have --with or am I missing anything?

Copy link
Member

Choose a reason for hiding this comment

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

The extension is "sodium", and thus we should use some --with-sodium to be consistent, (enable/with is not revelant here)

See ext/zip for ex, it have "--enable-zip" for the extension and "--with-libzip" for the library.

Copy link
Member

Choose a reason for hiding this comment

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

Sure that's what I meant. I was just replying in regards to the one of the options that you suggested. Basically it shouldn't be enable but with. In this case --with-sodium ofc.

@@ -0,0 +1,23 @@
Copyright (c) 2013-2017, Frank Denis
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't all core extension be under the PHP license? I know that there are some files under other licenses but is there actually a core extension with other primary license than the PHP license. If this would be the first one I think that this would be good to mention on the internal list unless it's been already discussed and I just missed it...

[libsodium](https://github.com/jedisct1/libsodium).

Full documentation here:
[Using Libsodium in PHP Projects](https://paragonie.com/book/pecl-libsodium),
Copy link
Member

Choose a reason for hiding this comment

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

Are there any plans to move docs to PHP?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. That would be a very good idea.


PHP_FUNCTION(sodium_memzero)
{
zval *buf_zv;
Copy link
Member

Choose a reason for hiding this comment

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

could the tab between tab and var be replaced with a single space to keep it more or less consistent with other exts.

Copy link
Contributor

Choose a reason for hiding this comment

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

I wish spaces could be used instead of having to mix tab and spaces.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is not mixing of spaces and tabs. Indentation is always with tabs and alignment with spaces, otherwise it is impossible to ensure consistent formatting across different tab configurations. You are already encountering this effect here on GitHub. Tabs are the best choice for indentation, because they allow configuration, but that is exactly not what you want when you carefully align code for readability, hence spaces are the best here. 😺

Copy link
Member

Choose a reason for hiding this comment

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

@jedisct1 Personally I prefer spaces for indentation. However much more important thing is to keep the coding style consistent. In most extensions and core, there is just a single spaces...

zval *buf_zv;

if (zend_parse_parameters(ZEND_NUM_ARGS(),
"z", &buf_zv) == FAILURE) {
Copy link
Member

Choose a reason for hiding this comment

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

wouldn't be better to indent it with less tabs? I think that 2 tabs (3 with the function indent) should be enough.

// $Id$
// vim:ft=javascript

ARG_WITH("libsodium", "for libsodium support", "no");
Copy link
Contributor

Choose a reason for hiding this comment

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

The ext name should be adjusted here, too. In further also the variable would be PHP_SODIUM. I'm going to add the library builds to the windows deps package already.

Thanks.

@LinuzLuzas LinuzLuzas mentioned this pull request Jun 9, 2017
@remicollet
Copy link
Member

remicollet commented Jun 12, 2017

=> remicollet@167bbb6

@weltling please check config.w32

BTW, I agree on changing license to PHP one, @paragonie-scott what do you think ?

@jedisct1
Copy link
Contributor

Is changing the license a requirement?

I'd like to stick to the BSD license, if compatible with PHP requirements. Or else, have it dual licensed.

@remicollet
Copy link
Member

PHP License is a BSD License, only changed to add the PHP name protection clause.

@remicollet
Copy link
Member

Is changing the license a requirement?

Probably no, but I have no real answer, can you please raise this on Internals ?

@remicollet
Copy link
Member

@paragonie-scott @jedisct1 BTW, if you are OK with my changes, I will merge it soon (at least, I'd like to see this before alpha2)

@remicollet
Copy link
Member

@remicollet
Copy link
Member

@jedisct1 @paragonie-scott ping

Copy link
Contributor

@Fleshgrinder Fleshgrinder left a comment

Choose a reason for hiding this comment

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

  • Formatting is inconsistent, often off (hint: tab for indentation and spaces for alignment), and not optimized for readability.
  • Exception messages are inconsistent and mostly not helpful for the user.
  • Many optional constants and functions, library providers can never be sure what is available and what isn't. This leads to many defined and function_exists checks and pollutes user-level code. I don't know why this is like that, I guess it depends on the sodium library version. In that case it seems better to define a minimum version, rather than having optional features.

PS: Function names are hard to understand (e.g. scalarmult, kx). I know that this is done to be a direct copy of the underlying library. I still believe that this is wrong.

zend_module_entry libsodium_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
Copy link
Contributor

Choose a reason for hiding this comment

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

Checking for the module API here seems unnecessary, this is shipped with the latest PHP only.


#ifndef PHP_FE_END
# define PHP_FE_END { NULL, NULL, NULL }
#endif
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems unnecessary as it should always be defined.

/* optional */
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
Copy link
Contributor

Choose a reason for hiding this comment

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

Would be great if the argument info declarations are close to their respective functions. I also believe that it would be better to use type constraints, instead of just taking mixed types.

#include <sodium.h>
#include <stdint.h>

#define ZSTR_TRUNCATE(zs, len) do { ZSTR_LEN(zs) = (len); } while(0)
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that it is a good idea to define a (global) Zend macro in an extension. This should rather be PHP_SODIUM_ZSTR_TRUNCATE, or moved to the other Zend macros.

Copy link
Contributor

Choose a reason for hiding this comment

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

Having that moved to other Zend macros would make sense, as it can be useful to other extensions.

Copy link
Member

Choose a reason for hiding this comment

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

Notice, we have zend_string_truncate

static zend_class_entry *sodium_exception_ce;

const int pass_rest_by_reference = 1;
const int pass_arg_by_reference = 0;
Copy link
Contributor

@Fleshgrinder Fleshgrinder Jun 15, 2017

Choose a reason for hiding this comment

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

Constants should be SCREAMING_SNAKE_CASE and probably static too.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think these are not used any more and could be dropped.

PHP_FUNCTION(sodium_increment);
PHP_FUNCTION(sodium_add);
PHP_FUNCTION(sodium_memcmp);
PHP_FUNCTION(sodium_memzero);
Copy link
Contributor

Choose a reason for hiding this comment

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

Defining the functions in the header is bad practice.


#define crypto_kx_BYTES crypto_scalarmult_BYTES
#define crypto_kx_PUBLICKEYBYTES crypto_scalarmult_SCALARBYTES
#define crypto_kx_SECRETKEYBYTES crypto_scalarmult_SCALARBYTES
Copy link
Contributor

@Fleshgrinder Fleshgrinder Jun 15, 2017

Choose a reason for hiding this comment

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

These should be prefixed with PHP_SODIUM_ and not crypto_kx_.

Copy link
Contributor

Choose a reason for hiding this comment

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

That would be pretty ugly and inconsistent.

These constants are defined in sodium >= 1.0.12, along with a better API so maybe the current crypto_kx function should be replaced with bindings to the sodium crypto_kx API.

Copy link
Contributor

Choose a reason for hiding this comment

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

Imho its inconsistent that these things are called crypto_ and not sodium_ from the library, but that is a different story. If that prefix is used by the library its fine.

Macros are always global, that is why it is important to have a clear naming scheme. In PHP that naming scheme is PHP_${EXT_NAME}_*.

@@ -0,0 +1,2682 @@

Copy link
Contributor

Choose a reason for hiding this comment

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

PHP license header?

(unsigned long long) ciphertext_len,
nonce, key) != 0) {
zend_string_free(msg);
RETURN_FALSE;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not an exception at this point?

Copy link
Contributor

Choose a reason for hiding this comment

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

Same here. Not a bug, likely not something the developers has to fix.

Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above, not a bug, but your function failed and should communicate that. Exceptions have nothing to do with bugs.

return;
}
if (ciphertext_len < crypto_secretbox_MACBYTES) {
RETURN_FALSE;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not an exception at this point?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's not a misuse.

Some possibly user-supplied data cannot be decrypted. That's normal, and should probably not trigger an exception, just like strcmp() doesn't throw an exception if the strings don't match.

Copy link
Contributor

Choose a reason for hiding this comment

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

strcmp is a bad example, as it does not use exceptions in the first place, and opts for error codes. You are using exceptions on the other hand.

Exceptions are not meant to point out something that requires fixing, in that case an error is asked for (or even a fatal error, depending on the severity). Exceptions indicate that your routine was not able to perform its duty and uphold its promise, in this case decoding something. The caller can catch that exception and try to recover, according to her domain.

Your current API violates this and requires double error handling:

try {
    if (sodium_crypto_secretbox_open('foo', 'bar', 'baz') === false) {
        // could not open, handle problem ...
    } else {
        // successfully opened, continue flow ...
    }
} catch (SodiumException $e) {
    // Actually an InvalidArgumentException ...
}

You might ask now why InvalidArgumentException is an exception and not an error. We cannot tell whether it was a user-level developer mistake or end-user supplied data that lead to the problem, hence, we throw an exception which allows the user-level developer to take appropriate action. This could be an error message that is displayed to the end-user.

Copy link
Contributor

Choose a reason for hiding this comment

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

This could be an error message that is displayed to the end-user. that's exactly what applications using crypto should avoid.

Copy link
Contributor

Choose a reason for hiding this comment

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

The double error handling looks fine to me. They cover very different cases. The former is not an error. And most people will not even try to catch the exception, which is fine as well, as it will only be thrown on misuse.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For future bikeshedding purposes: s/should/must/?

Copy link
Contributor

Choose a reason for hiding this comment

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

@paragonie-scott this is in informal discussion and not a standard. People should understand that every comment expresses a personal opinion and not the law.

@jedisct1 once more, the invalid arguments should result in an InvalidArgumentException and not a SodiumException, as the latter would indicate that sodium was unable to perform its duty.

Returning false is fine if you guys prefer a procedural interface, but in that case all functions should do so consistently. This would mean that the SodiumException is deleted and proper exceptions from SPL are used that convey the desired meaning:

  • InvalidArgumentException for invalid arguments
  • LengthException for the various length related stuff
  • Error for the various unknown internal error things
  • OverflowException/UnderflowException for the arithmetic problems

The SodiumException as it stands now has no meaning, as it is a catch-all for any- and everything related to the sodium extension without conveying any meaning.

@weltling
Copy link
Contributor

@remicollet

if (CHECK_LIB("libsodium.lib", "libsodium", PHP_LIBSODIUM) && CHECK_HEADER_ADD_INCLUDE("sodium.h", "CFLAGS_LIBSODIUM"))

still PHP_SODIUM and "CFLAGS_SODIUM" it should be. If i haven't overseen something, it should be it. But otherwise, probably would make sense to check Appveyor as well. I'll be checking after it's merged, but it might be quite short before tag.

Thanks.

@nikic
Copy link
Member

nikic commented Jun 15, 2017

@Fleshgrinder Thanks for the review. Just a procedural note to avoid confusion: We'd like to get this merged first and then perform any necessary cleanup or improvements after that, otherwise this is going to hang around forever. This PR should only deal with the remaining build system issues and not try to do any larger code changes.

@Fleshgrinder
Copy link
Contributor

@nikic thanks for the heads up. In that case my remarks should be disregarded. I am happy to help with these smaller things, as some changes (e.g. type constraints) must be performed before the final release of 7.2 or they will result in a BC discussion.

@remicollet
Copy link
Member

Rather (commits squashed/ammended) remicollet@a784069

@paragonie-scott can you pull above commit into this PR ?

@nikic
Copy link
Member

nikic commented Jun 16, 2017

@remicollet I've added you to the PHP organization, so you should be able to directly push to PRs in the future.

@remicollet
Copy link
Member

@nikic thanks, will be very helpful

@paragonie-scott
Copy link
Contributor Author

@remicollet I got a lot of merge conflicts when I tried to pull your changes in. Would your rather send a superseding PR?

@remicollet
Copy link
Member

remicollet commented Jun 16, 2017 via email

@remicollet
Copy link
Member

remicollet commented Jun 19, 2017

@paragonie-scott have you tried to merge my branch ? or only the single commit ?
The second should work...

wget https://github.com/remicollet/php-src/commit/a78406954f06ebc84cea396f20842f201ce8997d.patch
git am a78406954f06ebc84cea396f20842f201ce8997d.patch

@nikic
Copy link
Member

nikic commented Jun 23, 2017

I've pushed remi's changes to the PR.

return;
}
if (len1 != len2) {
zend_throw_exception(sodium_exception_ce, "memcmp(): arguments have different sizes", 0);
Copy link
Member

Choose a reason for hiding this comment

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

I think the message should be "memcmp(): arguments should have same size", since we tell users what we except, like other error messages in this file.

@sgolemon
Copy link
Member

@jedisct1 I'm not sure how looped into the conversation you've been, I've been using @paragonie-scott as my go-between because I wasn't clear who owned ext-sodium, but the LICENSE issue is probably our main blockers at this point. Anything to do with fixing up the code can be addressed post-merge, but pulling in an extension that's not under the PHP license would be unprecedented, so we'd like if you could re-license the extension to the PHP license.

If that's a blocker for you, we can potentially take the BSD license as-is, but to quote part of the internals conversation on the topic:

"""We copy and paste code between extensions. If different extensions use different copyrights doing this "correctly" becomes complicated. If all PHP-related code is using PHP License and copyright by The PHP Group this becomes easier."""

Naturally, this would not impact the license of libsodium itself, and you would retain your place in the CREDITS file.

@nikic
Copy link
Member

nikic commented Jun 30, 2017

@sgolemon As far as I'm aware relicensing of code is always tricky business requiring individual sign-off from all contributors. And what is being suggested here seems to go beyond a simple licensing change -- your quote also implies a transferal of copyright to the PHP group. I don't think that's a reasonable requirement, and it seems like even sketchier legal ground.

@sgolemon
Copy link
Member

https://github.com/jedisct1/libsodium-php/graphs/contributors has 13 contributors. 7 of these are trivial contributions. Of the remaining 5 (not counting @jedisct1), it's: You, @paragonie-scott, and @remicollet who are all trivial to get sign-off from, leaving @xor-zz and @wlejon to track down. That's pretty minimal.

Do you have a better solution?

@wlejon
Copy link

wlejon commented Jun 30, 2017

the work I did was also trivial - but if you need something from me, I'm happy to provide.

@jedisct1
Copy link
Contributor

I guess we don't have any choice to have that code merged. The PHP license can be added to the current one so that the code is dual licensed.

@sgolemon
Copy link
Member

@jedisct1 As I said, """If that's a blocker for you, we can potentially take the BSD license as-is""". The potential part of that means you're going to need to be present and responsive in the conversation, however. First, that means reading (which you don't seem to have) and responding (which you've done little of). @remicollet asked you to raise this issue on internals@ weeks ago and you neither responded to that here, nor raised the issue there.

Am I being a jerk about it right now? Yes. Because this RFC has been approved since February, yet at this rate we're going to end up hitting feature freeze without a merge because even the code review issues are being responded to in glacial time. I'm willing to clean the code up after merge, but licensing is important, and I'm not going to touch this code without a solid answer on licensing that protects the rest of php-src.

I'll translate your answer above as, "No, I refuse to change the license to PHP" which again, is fine. You also state you're willing to amend/qualify the license in some way, that's also doable. Unfortunately, I'm not a lawyer, and I'm also not the final authority for PHP. For both these reasons, this conversation needs to happen on the internals list.

@remicollet
Copy link
Member

For memory http://news.php.net/php.internals/99503

@sgolemon
Copy link
Member

sgolemon commented Jun 30, 2017

Or with threading for the whole picture: https://externals.io/thread/945 ;)

But again, please don't post responses here. Post them on internals@. If you post them here, then someone has to repeat your arguments there and that will just slow things down.

@jedisct1
Copy link
Contributor

jedisct1 commented Jul 1, 2017

Ok, how do we change the license then?

@sgolemon
Copy link
Member

sgolemon commented Jul 2, 2017

But again, please don't post responses here. Post them on internals@. If you post them here, then someone has to repeat your arguments there and that will just slow things down.

@paragonie-scott
Copy link
Contributor Author

We have unanimous consent from everyone who has contributed any changes to that repository, so let's make it happen.

@remicollet
Copy link
Member

remicollet commented Jul 9, 2017

@paragonie-scott can you please add the standard license headers and squash the commit ?

@paragonie-scott
Copy link
Contributor Author

@remicollet Done and done.

@weltling
Copy link
Contributor

@paragonie-scott here at least https://github.com/php/php-src/pull/2560/files#diff-5597f3b22c08f00df6221764b50ea1ebR7 the ext name is still "libsodium".

Thanks.

@paragonie-scott
Copy link
Contributor Author

Okay, will fix that ASAP.

Can we make all future corrections after it's merged?

@weltling
Copy link
Contributor

I don't mind, only mentioned this as it doesn't even compile on AppVeyor. No bikeshedding here :) I could fix it after it's merged as well.

Thanks.

@remicollet
Copy link
Member

Thanks for you patience.

Merged

@remicollet
Copy link
Member

BTW, can you check the "Authors" line in the header, I don't think this is correct

@remicollet remicollet closed this Jul 11, 2017
@remicollet
Copy link
Member

Hmm.. travis failure
E: Unable to locate package libsodium-dev

Despite seems to exist, https://packages.debian.org/search?keywords=libsodium&searchon=names

@remicollet
Copy link
Member

Please check d269aa2
@paragonie-scott @jedisct1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.