Closed marcbrevoort-cyberhive closed 3 years ago
That's probably something I should fix by moving them to a shared crate. You could try to use the pqcrypto
main crate, which has features nowadays to turn off algorithms.
Using the pqcrypto
main crate, while I can manage to get things to compile, the linker yields the same sort of output as described above. This could be due to the project using further crypto libs, but Cargo.lock
also suggests the pqcrypto master crate simply pulls in the other crates as dependencies:
[[package]]
name = "pqcrypto"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d3874384bf37d988b83f806d632e2f7fca69a8cd0338efaa64e8e7664573052"
dependencies = [
"pqcrypto-classicmceliece",
"pqcrypto-dilithium",
"pqcrypto-falcon",
"pqcrypto-frodo",
"pqcrypto-hqc",
"pqcrypto-kyber",
"pqcrypto-ntru",
"pqcrypto-rainbow",
"pqcrypto-saber",
"pqcrypto-sphincsplus",
"pqcrypto-traits",
]
This suggests the same duplicate bindings still occur in that case, which would explain that behaviour (though I haven't 100% established a causal relationship in this instance).
Interesting, I've used the pqcrypto crate without issue...
Interesting indeed. Have you used multiple algorithms at the same time? You mentioned a feature to turn off algorithms - how does one use that feature?
Turns out multiple pqcrypto crates isn't required; In an existing project, adding
pqcrypto = { version = "0.12.2", features = [ "pqcrypto-saber" ] }
to Cargo.toml and then adding a line
use pqcrypto::kem::saber;
is enough to make things blow up with a multitude of errors such as
/usr/bin/ld: /tmp/rustcnUlEqg/libpqcrypto_frodo-506a150556c3706e.rlib(aes.o): in function `aes192_ctx_release':
/home/mrjb/.cargo/registry/src/github.com-1ecc6299db9ec823/pqcrypto-frodo-0.4.5/pqclean/common/aes.c:656: multiple definition of `aes192_ctx_release'; /tmp/rustcnUlEqg/libpqcrypto_sphincsplus-4222d08462d80d63.rlib(aes.o):/home/mrjb/.cargo/registry/src/github.com-1ecc6299db9ec823/pqcrypto-sphincsplus-0.5.2/pqclean/common/aes.c:656: first defined here
... which is interesting since I'm not using frodo or sphincsplus, so I'm not sure why it even wants to link them in.
Now if instead I just use
pqcrypto-traits = { version = "0.3.2" }
pqcrypto-saber = { version = "0.1.5" }
and use pqcrypto-saber
in my code, things compile and link just fine.
However the moment I add
pqcrypto-classicmceliece = { version = "0.1.1" }
and
use pqcrypto_classicmceliece::mceliece460896::*;
the linker breaks down with
/usr/bin/ld: /tmp/rustcUYJYBi/libpqcrypto_saber-bb46a144ea0132aa.rlib(sp800-185.o): in function `cshake256':
/home/mrjb/.cargo/registry/src/github.com-1ecc6299db9ec823/pqcrypto-saber-0.1.5/pqclean/common/sp800-185.c:149: multiple definition of `cshake256'; /tmp/rustcUYJYBi/libpqcrypto_classicmceliece-3b59f51fe6b11caf.rlib(sp800-185.o):/home/mrjb/.cargo/registry/src/github.com-1ecc6299db9ec823/pqcrypto-classicmceliece-0.1.1/pqclean/common/sp800-185.c:149: first defined here
(and many more like it, all clashes between saber and mceliece).
I expect that if both packages depended on say, a pqcrypto_common
crate for the pqclean/common
stuff, there would be only one copy of each of any of the pqclean/common
files and the error would not occur.
You should also specify default-features = false
I don't have time to work on this crate in the coming week or so; I hope to have a look (and sync with upstream PQClean again) afterwards.
In the mean time you might want to consider using the oqs
crate anyway, it's a bit more polished.
The oqs crate seems to provide all I need and without linker issues - thanks for pointing me in that direction.
When using several pqcrypto crates (for instance saber and classicmceliece), it turns out both have their own copy of
pqclean/common/
which leads to linker errors such asNo doubt in practice
pqclean/common/sp800-185.c
is identical for both crates but in theory they might not be. Is there a version where the bindings to pqclean/common are split out to a separate package?