Make shlibsign output reproducible
Categories
(NSS :: Tools, enhancement)
Tracking
(Not tracked)
People
(Reporter: ghs9az, Assigned: rrelyea)
Details
Attachments
(3 files)
User Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36
Steps to reproduce:
shlibsign
is used to sign libfreebl3.so
, libnssdbm3.so
, and libsoftokn3.so
. shlibsign
generates a unique key on every invocation. This means that the resulting signature will always be different.
ChromeOS is working on switching to building packages using bazel and if things are not reproducible, we end up cache busting all the reverse dependencies anytime a rebuild happens. Debian also has a note about shsignlib not being reproducable: https://tests.reproducible-builds.org/debian/rb-pkg/unstable/amd64/nss.html.
We should add a mechanism that allows generating a stable CHK file. The simplest solution would be to hard code a HMAC key into shlibsign.c
and add a flag to use that instead of generating a random one. The other option is to have a flag that allows passing in the key or a file containing the key.
Thoughts?
Actual results:
I ran shsignlib
twice and ended up with different signatures:
shlibsign -vv -i /build/brya/usr/lib64/libfreebl3.so -o /tmp/3.chk
moduleSpec configdir='' certPrefix='' keyPrefix='' secmod='' flags=noCertDB, noModDB
Library File: /build/brya/usr/lib64/libfreebl3.so
Check File: /tmp/3.chk
Generate an HMAC key ...
Library File Size: 7584 bytes
key: 32 bytes
11 94 8a ac ee 93 c6 6f f5 fe
77 7f 52 fd f1 c4 8b a7 08 42
7a d2 9b 65 2b 79 a8 c1 fd bb
09 94
signature: 32 bytes
93 14 8a da ea c2 9e 7b d5 c1
f3 ad 47 ba 20 f4 b5 09 b4 4f
36 a6 1a b6 97 b8 be 97 d6 a7
b8 7d
shlibsign -vv -i /build/brya/usr/lib64/libfreebl3.so -o /tmp/3.chk
moduleSpec configdir='' certPrefix='' keyPrefix='' secmod='' flags=noCertDB, noModDB
Library File: /build/brya/usr/lib64/libfreebl3.so
Check File: /tmp/3.chk
Generate an HMAC key ...
Library File Size: 7584 bytes
key: 32 bytes
ca 9a 28 68 4e 43 dd 2d 86 a9
92 b4 d1 a6 da aa 63 c9 62 5a
dc a5 19 92 98 b7 39 b6 9e 8f
57 fa
signature: 32 bytes
70 79 b1 7f 1d 33 0b 23 68 94
ac 1b 43 26 47 38 1e 77 67 e7
c6 ed b0 2a 9e 33 06 e7 e9 49
66 e8
Expected results:
The output should have been identical.
Uses a hard coded HMAC key when the hash type is not specified.
I've attached a patch that uses a fixed HMAC key if the hash wasn't specified on the command line.
FWIW, I also pushed this up to the chromiumos repo: https://chromium-review.googlesource.com/c/chromiumos/overlays/chromiumos-overlay/+/5632908
Comment 3•4 months ago
|
||
Comment 4•4 months ago
|
||
I'm not a huge fan of fixed magic keys, so I've built on top of Rauls patch and created an option to hand in key-material from the commandline, in order to get the output reproducible.
Comment 5•4 months ago
|
||
Bob, I think this is sort-of your purview - what do you think? Also, I was curious what exactly FIPS says about the integrity self-test requirement. Would just hashing the library files with e.g. SHA256 and comparing the value be acceptable? Storing the secret HMAC key along with the HMAC itself doesn't provide any meaningful security...
Assignee | ||
Comment 6•4 months ago
|
||
So yes, I don't think we can do this (replace HMAC with Hash). FIPS explicitly requires signing (even though we pointed out that it's not real signing). At least we are able to sign with HMAC rather than DSA/ECDSA like we used to. These values are only relevant to FIPS mode (when your not in FIPS mode, they may be checked, but they aren't determinative.
I think msirringhaus's patch is the better idea. Chromiumos can have their own builds with their own fixed keys if variable keys causes them problems. The can even take other's prebuilt versions and sign them themselves with their own keys. My only comment on the patch would be there has got to be a hex 2 bin function somewhere in cmd/lib that we can use rather than coding a new one. If not we should put the hex2bin in cmd/lib for future use in other places.
Comment 7•4 months ago
|
||
The problem is that shlibsign was intentionally built to not use anything other than NSPR and libsoftokn, see bug 347037.
I didn't want to change that, so I can't really pull in anything external.
So, we would need to add that function to NSPR, make a new release of that, etc. Also I'm not 100% sure it would fit into NSPR in the first place.
To add insult to injury, the initial function I based this on is already copy&pasted in three different locations, too:
https://searchfox.org/mozilla-central/source/security/nss/cmd/bltest/blapitest.c#254
https://searchfox.org/mozilla-central/source/security/nss/cmd/fipstest/fipstest.c#59
https://searchfox.org/mozilla-central/source/security/nss/cmd/pk11gcmtest/pk11gcmtest.c#14
I'm also not happy with this, but currently see no 'easy' way to consolidate that. I'm open to suggestions, though! I'd be happy to also implement this the 'hard' way, if we can agree on one.
Assignee | ||
Comment 8•3 months ago
|
||
cmd/lib is a static library that all of cmd links with, so we could put it in cmd/lib and have all of those call into it.
Comment 9•3 months ago
|
||
Ok, after talking with our FIPS-people, it seems that in this particular situation the FIPS-standard only cares about the verification-part of the checksums, not how they are created. So we are free to link even lib/util, which has a dedicated function already, making this patch considerably shorter.
I've updated the patch accordingly (even though this basically reverts the Makefile-part of bug 347037).
Assignee | ||
Updated•3 months ago
|
Assignee | ||
Comment 10•3 months ago
|
||
Dana, For some reason lando doesn't work for me. I can land this, it's just I have to extract the patch and apply it, then check it into hg by hand, Can you push the lando button for me? (If not I'll go ahead and land this myself in the next day or so).
Comment 11•3 months ago
|
||
I don't actually have landing permissions for NSS. John?
Comment 12•3 months ago
|
||
Comment 13•3 months ago
•
|
||
This change is breaking NSS builds. Surprised that our CI didn't catch that. See https://github.com/mozilla/neqo/actions/runs/10157687760/job/28088270178#step:5:1306
cc -MMD -MF obj/cmd/shlibsign/shlibsign.shlibsign.o.d '-DSHLIB_SUFFIX="so"' '-DSHLIB_PREFIX="lib"' -DNSS_FIPS_DISABLED -DNSS_NO_INIT_SUPPORT -DNSS_X86_OR_X64 -DNSS_X64 -DNSS_USE_64 -DUSE_UTIL_DIRECTLY -DNO_NSPR_10_SUPPORT -DSSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -DLINUX2_1 -DLINUX -Dlinux -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_SOURCE -DSDB_MEASURE_USE_TEMP_DIR -DHAVE_STRERROR -DXP_UNIX -D_REENTRANT -DNSS_DISABLE_DBM -DNSS_DISABLE_LIBPKIX -DNDEBUG -I/home/runner/work/neqo/neqo/dist/Release/include/nspr -I/home/runner/work/neqo/neqo/dist/private/nss -I/home/runner/work/neqo/neqo/dist/public/nss -fPIC -pipe -ffunction-sections -fdata-sections -m64 -Werror -Wall -Wshadow -O2 -ggdb3 -fno-omit-frame-pointer -std=c99 -c ../../cmd/shlibsign/shlibsign.c -o obj/cmd/shlibsign/shlibsign.shlibsign.o
../../cmd/shlibsign/shlibsign.c: In function ‘shlibSignHMAC’:
../../cmd/shlibsign/shlibsign.c:1135:13: error: implicit declaration of function ‘SECU_HexString2SECItem’ [-Werror=implicit-function-declaration]
1135 | if (SECU_HexString2SECItem(NULL, &keyitem, key) == NULL) {
| ^~~~~~~~~~~~~~~~~~~~~~
../../cmd/shlibsign/shlibsign.c:1135:57: error: comparison between pointer and integer [-Werror]
1135 | if (SECU_HexString2SECItem(NULL, &keyitem, key) == NULL) {
| ^~
cc1: all warnings being treated as errors
Comment 14•3 months ago
•
|
||
I wonder if we can add a task to our CI that we can catch these type of bugs
Upd: ah, Lars told pretty much the same
Comment 15•3 months ago
|
||
Oh, sorry! I forgot an #include "basicutil.h"
, it seems. I think it slides through, if export NSS_ENABLE_WERROR=0
is set.
Does this get backed out now, or do I have to open a follow-up bug to submit the fix?
Comment 16•3 months ago
|
||
Updated•3 months ago
|
Comment 17•3 months ago
|
||
(In reply to msirringhaus from comment #15)
I think it slides through, if
export NSS_ENABLE_WERROR=0
is set.
Is the CI setting this? (It shouldn't.)
Comment 18•3 months ago
|
||
Just adding basicutils.h does not seem to solve that: https://treeherder.mozilla.org/jobs?repo=nss-try&revision=73498b0e1076
Comment 19•3 months ago
|
||
(In reply to Anna Weine from comment #18)
Just adding basicutils.h does not seem to solve that: https://treeherder.mozilla.org/jobs?repo=nss-try&revision=73498b0e1076
I don't think thats my bug now. Looks like fallout from https://phabricator.services.mozilla.com/D217915 ? There, dirent was removed, and now the build fails, because it wants to link dirent.o
Comment 20•3 months ago
|
||
Yes, I am checking the same thing
Comment 21•3 months ago
|
||
I'm think you have to remove those:
❯ rg dirent
lib/dbm/src/src.gyp
14: 'dirent.c',
lib/dbm/src/manifest.mn
25: dirent.c \
Then it builds locally for me.
Comment 22•3 months ago
|
||
Comment 23•3 months ago
|
||
I'm running the test build to check if all is ok now: https://treeherder.mozilla.org/jobs?repo=nss-try&revision=a0ab076e0353f8b94db409b8943d25161e9097ed
Comment 24•3 months ago
•
|
||
Martin, the patch is landed: https://hg.mozilla.org/projects/nss/rev/ee8fae86b323570b8c9126e26466b1426f641705
Comment 25•3 months ago
|
||
A patch has been attached on this bug, which was already closed. Filing a separate bug will ensure better tracking. If this was not by mistake and further action is needed, please alert the appropriate party. (Or: if the patch doesn't change behavior -- e.g. landing a test case, or fixing a typo -- then feel free to disregard this message)
Description
•