Hello there, I saw the recent addition of the version #define's, which are great, but a runtime function that I can call to find out libnettle's API is essential for dynamic bindings.
I maintain the Julia language bindings for Nettle https://github.com/staticfloat/Nettle.jl which loads the dynamic library and generates methods to use Nettle's cryptographic functions on the fly. This process does not use header files, it's similar to Python's ctypes functionality, and thus knowing which API version we're dealing with by only using the dynamic library itself is necessary. Most other projects have some method or other for determining this, as you guys have already discussed, but simply placing the information into a header file is not sufficient for this use case.
Is this something it would be possible to support?
Thanks! -E
Elliot Saba staticfloat@gmail.com writes:
I maintain the Julia language bindings for Nettle https://github.com/staticfloat/Nettle.jl which loads the dynamic library and generates methods to use Nettle's cryptographic functions on the fly.
Nice!
This process does not use header files, it's similar to Python's ctypes functionality, and thus knowing which API version we're dealing with by only using the dynamic library itself is necessary.
To some degree, I imagine you can solve the problem by looking up the symbols of interest using dlsym, and skip generation of corresponding julia methods if the symbol doesn't exist (but that won't help when there are incompatible changes to the behaviour) . You might also want to use the list
extern const struct nettle_hash * const nettle_hashes[];
(declared in nettle-meta.h).
Most other projects have some method or other for determining this, as you guys have already discussed, but simply placing the information into a header file is not sufficient for this use case.
I understand that a runtime method to look up the version of nettle can be useful in some cases. What level of detail do you need? Some alternatives:
1. Functions just returning the corresponding version.h values, like
int nettle_version_major (void) { return NETTLE_VERSION_MAJOR; }
int nettle_version_minor (void) { return NETTLE_VERSION_MINOR; }
2. Some struct including version numbers and possibly other configure information,
struct nettle_version_info { int major; int minor; ... };
extern const struct nettle_version_info nettle_version;
It's no big deal to add something like this, but I'm not sure what's really needed.
Regards, /Niels
Hello there! Thank you for your quick response:
Right now, the way we're trying to solve this is by using dlsym() to look for functions that are included in one API version, and not another. This isn't quite as easy as using a version number, but is what we will do to tell the difference between, e.g. 2.7.1 and 3.0.0.
Either of your solutions will work here, I have no preference. And we are indeed generating functions and types from within Julia, on the fly, based on the entries of nettle_hashes[]. Fun times! -E
On Fri, May 1, 2015 at 12:05 PM, Niels Möller nisse@lysator.liu.se wrote:
Elliot Saba staticfloat@gmail.com writes:
I maintain the Julia language bindings for Nettle https://github.com/staticfloat/Nettle.jl which loads the dynamic
library
and generates methods to use Nettle's cryptographic functions on the fly.
Nice!
This process does not use header files, it's similar to Python's ctypes functionality, and thus knowing which API version we're dealing with by only using the dynamic library itself is necessary.
To some degree, I imagine you can solve the problem by looking up the symbols of interest using dlsym, and skip generation of corresponding julia methods if the symbol doesn't exist (but that won't help when there are incompatible changes to the behaviour) . You might also want to use the list
extern const struct nettle_hash * const nettle_hashes[];
(declared in nettle-meta.h).
Most other projects have some method or other for determining this, as you guys have already discussed, but simply placing the information into a header file is not sufficient for this use case.
I understand that a runtime method to look up the version of nettle can be useful in some cases. What level of detail do you need? Some alternatives:
Functions just returning the corresponding version.h values, like
int nettle_version_major (void) { return NETTLE_VERSION_MAJOR; }
int nettle_version_minor (void) { return NETTLE_VERSION_MINOR; }
Some struct including version numbers and possibly other configure information,
struct nettle_version_info { int major; int minor; ... };
extern const struct nettle_version_info nettle_version;
It's no big deal to add something like this, but I'm not sure what's really needed.
Regards, /Niels
-- Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26. Internet email is subject to wholesale government surveillance.
Elliot Saba staticfloat@gmail.com writes:
Right now, the way we're trying to solve this is by using dlsym() to look for functions that are included in one API version, and not another. This isn't quite as easy as using a version number, but is what we will do to tell the difference between, e.g. 2.7.1 and 3.0.0.
Too bad there's no easy way (as far as I'm aware) to query the soname of a library opened with dlopen.
Either of your solutions will work here, I have no preference.
Below is a possible patch. Feedback appreciated.
It's about the simplest interface I can think of. One could use a plain constant, "extern const int nettle_version_major;" instead of the functions. Or use unsigned instead of int. But a function is perhaps more conventional.
Maybe one should also have functions returning the shared library version numbers? To adapt to ABI incompatibilities, the major shared library number (which is part of the soname) is likely the most useful piece of information.
And there's currently no "patch-level" version number, i.e. the final .1 in 3.1.1, neither in this patch, nor in version.h. It could be added if there are any use-cases for that.
Regards, /Niels
diff --git a/Makefile.in b/Makefile.in index 08efb7d..1bb750d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -133,6 +133,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \ umac-nh.c umac-nh-n.c umac-l2.c umac-l3.c \ umac-poly64.c umac-poly128.c umac-set-key.c \ umac32.c umac64.c umac96.c umac128.c \ + version.c \ write-be32.c write-le32.c write-le64.c \ yarrow256.c yarrow_key_event.c
diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make index 5d79320..aaab7a7 100644 --- a/testsuite/.test-rules.make +++ b/testsuite/.test-rules.make @@ -100,6 +100,9 @@ serpent-test$(EXEEXT): serpent-test.$(OBJEXT) twofish-test$(EXEEXT): twofish-test.$(OBJEXT) $(LINK) twofish-test.$(OBJEXT) $(TEST_OBJS) -o twofish-test$(EXEEXT)
+version-test$(EXEEXT): version-test.$(OBJEXT) + $(LINK) version-test.$(OBJEXT) $(TEST_OBJS) -o version-test$(EXEEXT) + knuth-lfib-test$(EXEEXT): knuth-lfib-test.$(OBJEXT) $(LINK) knuth-lfib-test.$(OBJEXT) $(TEST_OBJS) -o knuth-lfib-test$(EXEEXT)
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index 6bc1907..f5264ba 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -23,7 +23,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \ sha384-test.c sha512-test.c sha512-224-test.c sha512-256-test.c \ sha3-permute-test.c sha3-224-test.c sha3-256-test.c \ sha3-384-test.c sha3-512-test.c \ - serpent-test.c twofish-test.c \ + serpent-test.c twofish-test.c version-test.c \ knuth-lfib-test.c \ cbc-test.c ctr-test.c gcm-test.c eax-test.c ccm-test.c \ poly1305-test.c chacha-poly1305-test.c \ diff --git a/testsuite/version-test.c b/testsuite/version-test.c new file mode 100644 index 0000000..a472e3b --- /dev/null +++ b/testsuite/version-test.c @@ -0,0 +1,41 @@ +/* version-test.c + + Copyright (C) 2015 Niels Möller + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#include "testutils.h" + +void +test_main (void) +{ + /* This also checks that we don't by accident link with a different + version of nettle which is installed on the system. */ + ASSERT (nettle_version_major () == NETTLE_VERSION_MAJOR); + ASSERT (nettle_version_minor () == NETTLE_VERSION_MINOR); +} diff --git a/version.c b/version.c new file mode 100644 index 0000000..836f4eb --- /dev/null +++ b/version.c @@ -0,0 +1,48 @@ +/* version.c + + Copyright (C) 2015 Niels Möller + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "version.h" + +int +nettle_version_major (void) +{ + return NETTLE_VERSION_MAJOR; +} + +int +nettle_version_minor (void) +{ + return NETTLE_VERSION_MINOR; +} diff --git a/version.h.in b/version.h.in index 447e933..cf429f2 100644 --- a/version.h.in +++ b/version.h.in @@ -3,6 +3,7 @@ Information about library version.
Copyright (C) 2015 Red Hat, Inc. + Copyright (C) 2015 Niels Möller
This file is part of GNU Nettle.
@@ -50,6 +51,12 @@ extern "C" { # define GMP_NUMB_BITS @GMP_NUMB_BITS@ #endif
+int +nettle_version_major (void); + +int +nettle_version_minor (void); + #ifdef __cplusplus } #endif
The patch looks perfect. Thank you!
On Fri, May 1, 2015, 13:36 Niels Möller nisse@lysator.liu.se wrote:
Elliot Saba staticfloat@gmail.com writes:
Right now, the way we're trying to solve this is by using dlsym() to look for functions that are included in one API version, and not another.
This
isn't quite as easy as using a version number, but is what we will do to tell the difference between, e.g. 2.7.1 and 3.0.0.
Too bad there's no easy way (as far as I'm aware) to query the soname of a library opened with dlopen.
Either of your solutions will work here, I have no preference.
Below is a possible patch. Feedback appreciated.
It's about the simplest interface I can think of. One could use a plain constant, "extern const int nettle_version_major;" instead of the functions. Or use unsigned instead of int. But a function is perhaps more conventional.
Maybe one should also have functions returning the shared library version numbers? To adapt to ABI incompatibilities, the major shared library number (which is part of the soname) is likely the most useful piece of information.
And there's currently no "patch-level" version number, i.e. the final .1 in 3.1.1, neither in this patch, nor in version.h. It could be added if there are any use-cases for that.
Regards, /Niels
diff --git a/Makefile.in b/Makefile.in index 08efb7d..1bb750d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -133,6 +133,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \ umac-nh.c umac-nh-n.c umac-l2.c umac-l3.c \ umac-poly64.c umac-poly128.c umac-set-key.c \ umac32.c umac64.c umac96.c umac128.c \
version.c \ write-be32.c write-le32.c write-le64.c \ yarrow256.c yarrow_key_event.c
diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make index 5d79320..aaab7a7 100644 --- a/testsuite/.test-rules.make +++ b/testsuite/.test-rules.make @@ -100,6 +100,9 @@ serpent-test$(EXEEXT): serpent-test.$(OBJEXT) twofish-test$(EXEEXT): twofish-test.$(OBJEXT) $(LINK) twofish-test.$(OBJEXT) $(TEST_OBJS) -o twofish-test$(EXEEXT)
+version-test$(EXEEXT): version-test.$(OBJEXT)
$(LINK) version-test.$(OBJEXT) $(TEST_OBJS) -o
version-test$(EXEEXT)
knuth-lfib-test$(EXEEXT): knuth-lfib-test.$(OBJEXT) $(LINK) knuth-lfib-test.$(OBJEXT) $(TEST_OBJS) -o knuth-lfib-test$(EXEEXT)
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index 6bc1907..f5264ba 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -23,7 +23,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \ sha384-test.c sha512-test.c sha512-224-test.c sha512-256-test.c \ sha3-permute-test.c sha3-224-test.c sha3-256-test.c \ sha3-384-test.c sha3-512-test.c \
serpent-test.c twofish-test.c \
serpent-test.c twofish-test.c version-test.c \ knuth-lfib-test.c \ cbc-test.c ctr-test.c gcm-test.c eax-test.c ccm-test.c
\ poly1305-test.c chacha-poly1305-test.c \ diff --git a/testsuite/version-test.c b/testsuite/version-test.c new file mode 100644 index 0000000..a472e3b --- /dev/null +++ b/testsuite/version-test.c @@ -0,0 +1,41 @@ +/* version-test.c
- Copyright (C) 2015 Niels Möller
- This file is part of GNU Nettle.
- GNU Nettle is free software: you can redistribute it and/or
- modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
- or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
- or both in parallel, as here.
- GNU Nettle is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received copies of the GNU General Public License and
- the GNU Lesser General Public License along with this program. If
- not, see http://www.gnu.org/licenses/.
+*/
+#include "testutils.h"
+void +test_main (void) +{
- /* This also checks that we don't by accident link with a different
version of nettle which is installed on the system. */
- ASSERT (nettle_version_major () == NETTLE_VERSION_MAJOR);
- ASSERT (nettle_version_minor () == NETTLE_VERSION_MINOR);
+} diff --git a/version.c b/version.c new file mode 100644 index 0000000..836f4eb --- /dev/null +++ b/version.c @@ -0,0 +1,48 @@ +/* version.c
- Copyright (C) 2015 Niels Möller
- This file is part of GNU Nettle.
- GNU Nettle is free software: you can redistribute it and/or
- modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
- or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
- or both in parallel, as here.
- GNU Nettle is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received copies of the GNU General Public License and
- the GNU Lesser General Public License along with this program. If
- not, see http://www.gnu.org/licenses/.
+*/
+#if HAVE_CONFIG_H +# include "config.h" +#endif
+#include "version.h"
+int +nettle_version_major (void) +{
- return NETTLE_VERSION_MAJOR;
+}
+int +nettle_version_minor (void) +{
- return NETTLE_VERSION_MINOR;
+} diff --git a/version.h.in b/version.h.in index 447e933..cf429f2 100644 --- a/version.h.in +++ b/version.h.in @@ -3,6 +3,7 @@ Information about library version.
Copyright (C) 2015 Red Hat, Inc.
Copyright (C) 2015 Niels Möller
This file is part of GNU Nettle.
@@ -50,6 +51,12 @@ extern "C" { # define GMP_NUMB_BITS @GMP_NUMB_BITS@ #endif
+int +nettle_version_major (void);
+int +nettle_version_minor (void);
#ifdef __cplusplus } #endif
-- Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26. Internet email is subject to wholesale government surveillance.
Elliot Saba staticfloat@gmail.com writes:
The patch looks perfect. Thank you!
Perfect or not, it's now pushed to the repository.
Regards, /Niels
nettle-bugs@lists.lysator.liu.se