liboqs icon indicating copy to clipboard operation
liboqs copied to clipboard

Add cf protection to assembler files

Open beldmit opened this issue 11 months ago • 26 comments

Describe the bug Our annobin check has found out that the library doesn't implement the CET protection https://sourceware.org/annobin/annobin.html/Test-cf-protection.html because of lack of the corresponding code in ASM files (see the example in the link). SO even when the C sources are compiled with -fcf-protection the protection is still not enabled

beldmit avatar Jan 07 '25 13:01 beldmit

An example patch:

diff -rup liboqs-0.12.0.orig/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-768_avx2/invntt.S liboqs-0.12.0/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-768_avx2/invntt.S
--- liboqs-0.12.0.orig/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-768_avx2/invntt.S	2025-01-06 10:08:13.282017683 +0000
+++ liboqs-0.12.0/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-768_avx2/invntt.S	2025-01-06 10:09:33.407463609 +0000
@@ -183,6 +183,7 @@ vmovdqa		%ymm11,(64*\off+176)*2(%rdi)
 .text
 .global cdecl(invntt_avx)
 cdecl(invntt_avx):
+ENDBR64
 vmovdqa         _16XQ*2(%rsi),%ymm0
 
 intt_levels0t5	0
@@ -191,3 +192,20 @@ intt_levels0t5	1
 intt_level6	0
 intt_level6	1
 ret
+
+	.section	.note.gnu.property,"a"
+	.align 8
+	.long	 1f - 0f
+	.long	 4f - 1f
+	.long	 5
+0:
+	.string	 "GNU"
+1:
+	.align 8
+	.long	 0xc0000002
+	.long	 3f - 2f
+2:
+	.long	 0x3
+3:
+	.align 8
+4:

The same should be implemented for all the ASM sources

beldmit avatar Jan 07 '25 13:01 beldmit

Thanks for the report. Is it accurate to say that this is something that should ideally be fixed upstream? (i.e., in https://github.com/pq-crystals/kyber for this example)

SWilson4 avatar Jan 07 '25 13:01 SWilson4

Yes.

beldmit avatar Jan 07 '25 14:01 beldmit

This looks like a "mechanical" (automat-able) code addition: Am I right with this @beldmit ? All that's needed is adding these lines (always the same?!) to all .S files? Or is there more to it? Or asked differently, could you add such a cat cfgnusection.S >> *.S script to your distro? If that were the case, we could of course also do it in liboqs and not wait for all upstreams to do this.

baentsch avatar Jan 07 '25 16:01 baentsch

Unfortunately, it's not enough

Quoting the link https://sourceware.org/annobin/annobin.html/Test-cf-protection.html

If an assembler source file is used as part of an application then it too needs to be updated. Any location in the source code where an indirect branch or function call can land must now have either ENDBR64 (for 64-bit assembler) or ENDBR32 (for 32-bit assembler) as the first instruction executed.

beldmit avatar Jan 07 '25 16:01 beldmit

Thanks for the clarification/pointer. In that case, it's a task for the upstreams, indeed.

baentsch avatar Jan 07 '25 17:01 baentsch

Looping @hanno-becker @mkannwischer @praveksharma: Does mlkem-native implement these protections?

SWilson4 avatar Feb 07 '25 14:02 SWilson4

Looping @hanno-becker @mkannwischer @praveksharma: Does mlkem-native implement these protections?

Not yet. I opened an issue to track: https://github.com/pq-code-package/mlkem-native/pull/762 I have a draft PR https://github.com/pq-code-package/mlkem-native/pull/761, but still need to work around some issues.

mkannwischer avatar Feb 08 '25 04:02 mkannwischer

Looping @hanno-becker @mkannwischer @praveksharma: Does mlkem-native implement these protections?

Not yet. I opened an issue to track: https://github.com/pq-code-package/mlkem-native/pull/762 I have a draft PR https://github.com/pq-code-package/mlkem-native/pull/761, but still need to work around some issues.

We added it to mlkem-native now. @beldmit could you please have a look and let us know if that works for you.

mkannwischer avatar Feb 08 '25 09:02 mkannwischer

@mkannwischer We're thinking of doing a liboqs release in mid-March. Would there be a tagged mlkem-native release sometime before then that would include this (and other recent updates) that we could include in our release?

dstebila avatar Feb 26 '25 00:02 dstebila

@mkannwischer We're thinking of doing a liboqs release in mid-March. Would there be a tagged mlkem-native release sometime before then that would include this (and other recent updates) that we could include in our release?

Yes, we can certainly create a release soon. When would you need that at the latest? If we do want to include the extended API we will need a few more days.

mkannwischer avatar Feb 26 '25 05:02 mkannwischer

If we stick to the existing standard FIPS 203 API for the release, we can wrap things up quickly. It depends on whether you want/need the extended API for the next release, really.

hanno-becker avatar Feb 26 '25 05:02 hanno-becker

I remember about this task and will try to check it

beldmit avatar Feb 26 '25 06:02 beldmit

When would you need that at the latest?

As stated in https://github.com/open-quantum-safe/liboqs/issues/2028#issuecomment-2684252607 I'm sure we'd rather relax a tentative "mid March" release date than not include valuable additions.

It depends on whether you want/need the extended API for the next release, really.

Question back (and to @SWilson4 ): What does this extended API offer? Is it not required for landing https://github.com/open-quantum-safe/liboqs/pull/2070 , is it?

baentsch avatar Feb 26 '25 08:02 baentsch

I used the following command: LDFLAGS=-Wl,-z,now CFLAGS=-fcf-protection=full cmake -GNinja -DBUILD_SHARED_LIBS=ON -DOQS_USE_AES_OPENSSL=ON -DOQS_USE_AES_INSTRUCTIONS=OFF -DOQS_DIST_BUILD=ON -DOQS_ALGS_ENABLED=NIST -DOQS_USE_SHA3_OPENSSL=ON -DOQS_DLOPEN_OPENSSL=ON -DCMAKE_BUILD_TYPE=Release -LAH ..

and

$ annocheck -f lib/liboqs.so
annocheck: Version 12.69.
Hardened: liboqs.so: FAIL: gaps test because gaps were detected in the annobin coverage 
Hardened: liboqs.so: FAIL: cf-protection test because no .note.gnu.property section = no control flow information 
Hardened: liboqs.so: FAIL: property-note test because a property note was found but it shows that cf-protection is not enabled 
Hardened: Rerun annocheck with --verbose to see more information on the tests.
Hardened: liboqs.so: Overall: FAIL.

beldmit avatar Feb 26 '25 16:02 beldmit

Thanks for checking @beldmit -- but as the issue is not resolved, this failure is expected, right? Then, is annocheck a RHEL-only tool or could it also be used as part of a vendor-agnostic CI pipeline (didn't find it by apt search)?

baentsch avatar Feb 26 '25 17:02 baentsch

It is a part of Fedora, I believe:

$ yum info annobin-annocheck
Updating and loading repositories:
Name            : annobin-annocheck
Epoch           : 0
Version         : 12.69
Release         : 1.fc41
Architecture    : x86_64
Installed size  : 333.0 KiB
Source          : annobin-12.69-1.fc41.src.rpm
From repository : <unknown>
Summary         : A tool for checking the security hardening status of binaries
URL             : https://sourceware.org/annobin/
License         : GPL-3.0-or-later AND LGPL-2.0-or-later AND (GPL-2.0-or-later WITH GCC-exception-2.0) AND (LGPL-2.0-or-later WITH GCC-exception-2.0) AND GFDL-1.3-or-later
Description     : Installs the annocheck program which uses the notes generated by annobin to
                : check that the specified files were compiled with the correct security
                : hardening options.
Vendor          : Fedora Project

beldmit avatar Feb 26 '25 17:02 beldmit

Even when the updated mlkem-native implementation lands, this check will still likely fail due to assembly files in other algorithms (e.g., McEliece). However, if we could get it to run in CI on a minimal ML-KEM build, that might be cool.

SWilson4 avatar Feb 26 '25 20:02 SWilson4

Yes, it makes sense

beldmit avatar Feb 26 '25 21:02 beldmit

this check will still likely fail due to assembly files in other algorithms (e.g., McEliece)

Not really: Please note the presence of -DOQS_ALGS_ENABLED=NIST above. Hence, the above won't be a problem -- as long as the new CI test also IMO primarily targets (only?) that config option.

baentsch avatar Feb 27 '25 09:02 baentsch

Sorry, I missed that only the ML-KEM code is changed, so I can repeat the test if you give me proper build options

beldmit avatar Feb 27 '25 10:02 beldmit

Sorry, I missed that only the ML-KEM code is changed, so I can repeat the test if you give me proper build options

FWIW and AFAIK, the ML-KEM code imported to OQS did not yet get changed to add this protection (right @mkannwischer @SWilson4 ?), so I'd recommend you wait with re-test until that has happened @beldmit .

baentsch avatar Feb 27 '25 11:02 baentsch

Sorry, I missed that only the ML-KEM code is changed, so I can repeat the test if you give me proper build options

FWIW and AFAIK, the ML-KEM code imported to OQS did not yet get changed to add this protection (right @mkannwischer @SWilson4 ?), so I'd recommend you wait with re-test until that has happened @beldmit .

Yes, we have yet to update in liboqs.

mkannwischer avatar Feb 27 '25 12:02 mkannwischer

Not really: Please note the presence of -DOQS_ALGS_ENABLED=NIST above. Hence, the above won't be a problem -- as long as the new CI test also IMO primarily targets (only?) that config option.

Ah, I missed that—though I don't think we actually have a "NIST" option for alg selection (the documented ones are STD, NIST_R4, NIST_ON_RAMP), so perhaps this config is building all algs anyway. Even if it's restricted to standardized algs, ML-DSA will still have assembly files that don't implement the protection.

SWilson4 avatar Feb 27 '25 14:02 SWilson4

Not really: Please note the presence of -DOQS_ALGS_ENABLED=NIST above. Hence, the above won't be a problem -- as long as the new CI test also IMO primarily targets (only?) that config option.

Ah, I missed that—though I don't think we actually have a "NIST" option for alg selection (the documented ones are STD, NIST_R4, NIST_ON_RAMP), so perhaps this config is building all algs anyway. Even if it's restricted to standardized algs, ML-DSA will still have assembly files that don't implement the protection.

True, mldsa currently still has the old/less-maintained provenance. And the config setting indeed seems worth while checking out: What are you really using for Fedora/RHEL @beldmit ?

baentsch avatar Feb 27 '25 14:02 baentsch

I tried to duplicate this test now that the mlkem-native implementation has been updated. I observed something weird in the process:

  • After the initial configure and build commands, the test fails.
  • If the configure and build commands are repeated (without cleaning out the build directory) the test passes.

The behaviour is the same on both 0.12.0 (before the ML-KEM code was updated to include cf protection) and the latest main (which includes ML-KEM code with cf protection).

This seems to indicate a bug in either our build system or annocheck. Tagging @beldmit for more insight.


Here's my testing setup in case anyone else wants to duplicate my results:

Directory structure

tree
.
├── check_cf.sh
└── Dockerfile

1 directory, 2 files

Dockerfile

FROM fedora:latest

RUN dnf install -y annocheck cmake git gcc ninja openssl-devel

COPY check_cf.sh /root

WORKDIR /root

RUN git clone https://github.com/open-quantum-safe/liboqs.git liboqs

ENTRYPOINT ["./check_cf.sh"]

check_cf.sh

#!/bin/sh

build_liboqs() {
	LDFLAGS=-Wl,-z,now CFLAGS=-fcf-protection=full cmake -GNinja -DBUILD_SHARED_LIBS=ON -DOQS_USE_AES_OPENSSL=ON -DOQS_USE_AES_INSTRUCTIONS=OFF -DOQS_DIST_BUILD=ON -DOQS_USE_SHA3_OPENSSL=ON -DOQS_DLOPEN_OPENSSL=ON -DCMAKE_BUILD_TYPE=Release -DOQS_MINIMAL_BUILD="KEM_ml_kem_512" ..
	ninja
}

cd liboqs

git checkout a20597c # current main
git clean -xdf

mkdir build && cd build
build_liboqs
annocheck -f --skip-gaps --verbose lib/liboqs.so
build_liboqs
annocheck -f --skip-gaps --verbose lib/liboqs.so

cd ..

git checkout 0.12.0
git clean -xdf

mkdir build && cd build
build_liboqs
annocheck -f --skip-gaps --verbose lib/liboqs.so
build_liboqs
annocheck -f --skip-gaps --verbose lib/liboqs.so

To execute:

docker build -t check-cf .
docker run --rm check-cf

SWilson4 avatar Mar 25 '25 16:03 SWilson4