diff --git a/.gitignore b/.gitignore index a4fe1ed628..4225452b8d 100644 --- a/.gitignore +++ b/.gitignore @@ -419,6 +419,7 @@ tests/fallback-scsv tests/finished tests/fips-mode-pthread tests/fips-override-test +tests/fips-rsa-key-sizes tests/fips-test tests/gc tests/global-init @@ -863,6 +864,7 @@ tests/tls13-without-timeout-func tests/tls13/anti_replay tests/tls13/change_cipher_spec tests/tls13/compress-cert +tests/tls13/compress-cert-cli tests/tls13/compress-cert-neg tests/tls13/compress-cert-neg2 tests/tls13/cookie diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 38f551ef6c..9b49210c00 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -29,7 +29,7 @@ variables: CHECKJOBS: 16 cache: - key: "$CI_JOB_NAME-ver25" + key: "$CI_JOB_NAME-ver26" paths: - cache/ @@ -50,6 +50,8 @@ default: - *prepare-ccache - ccache -s + interruptible: true + .bootstrap: stage: bootstrap tags: @@ -366,6 +368,37 @@ fedora-minimal/test: needs: - fedora-minimal/build +fedora-interop/test: + extends: + - .test + - .fedora + dependencies: + - fedora-minimal/build + needs: + - fedora-minimal/build + parallel: + matrix: + - COMPONENT: + - openssl + #- nss # currently fails on Fedora due to NSS bug + TYPE: + - 2way + #- 3way # these tests take too long, plan is to split them + #- 4way + #- 5way + #- p256 + #- p384 + #- p521 + #- rsae + #- rsapss + allow_failure: true + script: + - cd tests/suite/tls-interoperability/ + - echo "Tests to run:" + - tmt run plans -n interop tests -f "tag:interop-gnutls" -f "tag:interop-$TYPE" -f "tag:interop-$COMPONENT" discover -v + - echo "Run the tests:" + - tmt run -a plans -n interop tests -f "tag:interop-gnutls" -f "tag:interop-$TYPE" -f "tag:interop-$COMPONENT" provision -h local execute -h tmt --interactive + fedora-SSL-3.0/build: extends: - .build diff --git a/.gitmodules b/.gitmodules index 2400cfb628..ff0b12fa73 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,6 @@ [submodule "devel/cligen"] path = cligen url = https://gitlab.com/gnutls/cligen.git +[submodule "tests/suite/tls-interoperability"] + path = tests/suite/tls-interoperability + url = https://gitlab.com/redhat-crypto/tests/interop.git diff --git a/NEWS b/NEWS index dac10b0c24..beaa5ebae8 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,32 @@ Copyright (C) 2000-2016 Free Software Foundation, Inc. Copyright (C) 2013-2019 Nikos Mavrogiannopoulos See the end for copying conditions. +* Version 3.7.8 (released 2022-09-27) + +** libgnutls: In FIPS140 mode, RSA signature verification is an approved + operation if the key has modulus with known sizes (1024, 1280, + 1536, and 1792 bits), in addition to any modulus sizes larger than + 2048 bits, according to SP800-131A rev2. + +** libgnutls: gnutls_session_channel_binding performs additional checks when + GNUTLS_CB_TLS_EXPORTER is requested. According to RFC9622 4.2, the + "tls-exporter" channel binding is only usable when the handshake is + bound to a unique master secret (i.e., either TLS 1.3 or extended + master secret extension is negotiated). Otherwise the function now + returns error. + +** libgnutls: usage of the following functions, which are designed to + loosen restrictions imposed by allowlisting mode of configuration, + has been additionally restricted. Invoking them is now only allowed + if system-wide TLS priority string has not been initialized yet: +gnutls_digest_set_secure +gnutls_sign_set_secure +gnutls_sign_set_secure_for_certs +gnutls_protocol_set_enabled + +** API and ABI modifications: +No changes since last version. + * Version 3.7.7 (released 2022-07-28) ** libgnutls: Fixed double free during verification of pkcs7 signatures. diff --git a/bootstrap.conf b/bootstrap.conf index 9f6ffd8880..ca7c0123b4 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -23,7 +23,7 @@ gnulib_tool_option_extras="--without-tests --avoid=alignof-tests --avoid=lock-te use_libtool=1 checkout_only_file= local_gl_dir=gl/override/ -required_submodules="tests/suite/tls-fuzzer/python-ecdsa tests/suite/tls-fuzzer/tlsfuzzer tests/suite/tls-fuzzer/tlslite-ng cligen devel/abi-dump devel/nettle devel/openssl devel/libtasn1" +required_submodules="tests/suite/tls-fuzzer/python-ecdsa tests/suite/tls-fuzzer/tlsfuzzer tests/suite/tls-fuzzer/tlslite-ng tests/suite/tls-interoperability cligen devel/abi-dump devel/nettle devel/openssl devel/libtasn1" # Those modules are common to lib/ and src/. common_modules=" diff --git a/cfg.mk b/cfg.mk index cfd835f303..a135b66f72 100644 --- a/cfg.mk +++ b/cfg.mk @@ -212,7 +212,7 @@ lib/accelerated/x86/elf/%.s: devel/perlasm/%.pl .submodule.stamp cat $<.license $@.tmp > $@ && rm -f $@.tmp echo "" >> $@ echo ".section .note.GNU-stack,\"\",%progbits" >> $@ - sed -i 's/OPENSSL_ia32cap_P/_gnutls_x86_cpuid_s/g' $@ + sed -i 's/OPENSSL_ia32cap_P/GNUTLS_x86_cpuid_s/g' $@ lib/accelerated/x86/coff/%-x86.s: devel/perlasm/%-x86.pl .submodule.stamp CC=gcc perl $< coff \ @@ -220,7 +220,7 @@ lib/accelerated/x86/coff/%-x86.s: devel/perlasm/%-x86.pl .submodule.stamp $@.tmp cat $<.license $@.tmp > $@ && rm -f $@.tmp echo "" >> $@ - sed -i 's/OPENSSL_ia32cap_P/_gnutls_x86_cpuid_s/g' $@ + sed -i 's/OPENSSL_ia32cap_P/GNUTLS_x86_cpuid_s/g' $@ lib/accelerated/x86/coff/%-x86_64.s: devel/perlasm/%-x86_64.pl .submodule.stamp CC=gcc perl $< mingw64 \ @@ -228,7 +228,7 @@ lib/accelerated/x86/coff/%-x86_64.s: devel/perlasm/%-x86_64.pl .submodule.stamp $@.tmp cat $<.license $@.tmp > $@ && rm -f $@.tmp echo "" >> $@ - sed -i 's/OPENSSL_ia32cap_P/_gnutls_x86_cpuid_s/g' $@ + sed -i 's/OPENSSL_ia32cap_P/GNUTLS_x86_cpuid_s/g' $@ lib/accelerated/x86/macosx/%.s: devel/perlasm/%.pl .submodule.stamp CC=gcc perl $< macosx \ @@ -236,7 +236,7 @@ lib/accelerated/x86/macosx/%.s: devel/perlasm/%.pl .submodule.stamp $@.tmp cat $<.license $@.tmp > $@ && rm -f $@.tmp echo "" >> $@ - sed -i 's/OPENSSL_ia32cap_P/_gnutls_x86_cpuid_s/g' $@ + sed -i 's/OPENSSL_ia32cap_P/GNUTLS_x86_cpuid_s/g' $@ lib/accelerated/aarch64/elf/%.s: devel/perlasm/%.pl .submodule.stamp rm -f $@tmp diff --git a/cligen b/cligen index be90038582..ed2ed7b19a 160000 --- a/cligen +++ b/cligen @@ -1 +1 @@ -Subproject commit be900385825c05fe3c672d2aed02f060790d2d18 +Subproject commit ed2ed7b19a5bcbc0f39505722058befc923eeeda diff --git a/configure.ac b/configure.ac index 96894b0be3..e78bcc1698 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.64) dnl when updating version also update LT_REVISION in m4/hooks.m4 -AC_INIT([GnuTLS], [3.7.7], [bugs@gnutls.org]) +AC_INIT([GnuTLS], [3.7.8], [bugs@gnutls.org]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIRS([m4 src/gl/m4 lib/unistring/m4]) AC_CANONICAL_HOST diff --git a/doc/cha-bib.texi b/doc/cha-bib.texi index 4df5e98f90..20dab0a99f 100644 --- a/doc/cha-bib.texi +++ b/doc/cha-bib.texi @@ -275,4 +275,8 @@ Computer Science No. 1465 (Rafael Hirschfeld, ed.), February 1998), pages 178--183, available from @url{https://people.csail.mit.edu/rivest/Rivest-CanWeEliminateCertificateRevocationLists.pdf}. +@item @anchor{RFC9266}[RFC9266] +S. Whited, "Channel Bindings for TLS 1.3", +July 2022, available from @url{https://www.ietf.org/rfc/rfc9266.txt}. + @end table diff --git a/doc/cha-gtls-app.texi b/doc/cha-gtls-app.texi index bd4447822b..56ca472ecd 100644 --- a/doc/cha-gtls-app.texi +++ b/doc/cha-gtls-app.texi @@ -2201,9 +2201,12 @@ background and discussion see @xcite{RFC5056}. In @acronym{GnuTLS} you can extract a channel binding using the @funcref{gnutls_session_channel_binding} function. Currently only the -type @code{GNUTLS_CB_TLS_UNIQUE} is supported, which corresponds to -the @code{tls-unique} channel binding for TLS defined in -@xcite{RFC5929}. +following types are supported: + +@itemize +@item @code{GNUTLS_CB_TLS_UNIQUE}: corresponds to the @code{tls-unique} channel binding for TLS defined in @xcite{RFC5929} +@item @code{GNUTLS_CB_TLS_EXPORTER}: corresponds to the @code{tls-exporter} channel binding for TLS defined in @xcite{RFC9266} +@end itemize The following example describes how to print the channel binding data. Note that it must be run after a successful TLS handshake. diff --git a/doc/latex/gnutls.bib b/doc/latex/gnutls.bib index a30f079f3d..ee9dea0d4f 100644 --- a/doc/latex/gnutls.bib +++ b/doc/latex/gnutls.bib @@ -538,3 +538,17 @@ @misc{rfc4418 url="https://www.ietf.org/rfc/rfc4418.txt", } +@misc{rfc9266, + series = {Request for Comments}, + number = 9266, + howpublished = {RFC 9266}, + publisher = {RFC Editor}, + doi = {10.17487/RFC9266}, + url = {https://www.rfc-editor.org/info/rfc9266}, + author = {Sam Whited}, + title = {{Channel Bindings for TLS 1.3}}, + pagetotal = 7, + year = 2022, + month = jul, + abstract = {This document defines a channel binding type, tls-exporter, that is compatible with TLS 1.3 in accordance with RFC 5056, "On the Use of Channel Bindings to Secure Channels". Furthermore, it updates the default channel binding to the new binding for versions of TLS greater than 1.2. This document updates RFCs 5801, 5802, 5929, and 7677.}, +} \ No newline at end of file diff --git a/lib/accelerated/x86/coff/aesni-x86.s b/lib/accelerated/x86/coff/aesni-x86.s index c6aa1a1e2a..92e5431f19 100644 --- a/lib/accelerated/x86/coff/aesni-x86.s +++ b/lib/accelerated/x86/coff/aesni-x86.s @@ -2873,7 +2873,7 @@ __aesni_set_encrypt_key: .L112pic: popl %ebx leal .Lkey_const-.L112pic(%ebx),%ebx - leal __gnutls_x86_cpuid_s,%ebp + leal _GNUTLS_x86_cpuid_s,%ebp movups (%eax),%xmm0 xorps %xmm4,%xmm4 movl 4(%ebp),%ebp @@ -3251,5 +3251,5 @@ _aesni_set_decrypt_key: .byte 83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83 .byte 32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115 .byte 115,108,46,111,114,103,62,0 -.comm __gnutls_x86_cpuid_s,16 +.comm _GNUTLS_x86_cpuid_s,16 diff --git a/lib/accelerated/x86/coff/aesni-x86_64.s b/lib/accelerated/x86/coff/aesni-x86_64.s index 3a07713e4e..0094f596c1 100644 --- a/lib/accelerated/x86/coff/aesni-x86_64.s +++ b/lib/accelerated/x86/coff/aesni-x86_64.s @@ -1258,7 +1258,7 @@ aesni_ctr32_encrypt_blocks: leaq 7(%r8),%r9 movl %r10d,96+12(%rsp) bswapl %r9d - movl _gnutls_x86_cpuid_s+4(%rip),%r10d + movl GNUTLS_x86_cpuid_s+4(%rip),%r10d xorl %ebp,%r9d andl $71303168,%r10d movl %r9d,112+12(%rsp) @@ -3869,7 +3869,7 @@ aesni_cbc_encrypt: movdqa %xmm5,%xmm14 movdqu 80(%rdi),%xmm7 movdqa %xmm6,%xmm15 - movl _gnutls_x86_cpuid_s+4(%rip),%r9d + movl GNUTLS_x86_cpuid_s+4(%rip),%r9d cmpq $0x70,%rdx jbe .Lcbc_dec_six_or_seven @@ -4418,7 +4418,7 @@ __aesni_set_encrypt_key: movl $268437504,%r10d movups (%rcx),%xmm0 xorps %xmm4,%xmm4 - andl _gnutls_x86_cpuid_s+4(%rip),%r10d + andl GNUTLS_x86_cpuid_s+4(%rip),%r10d leaq 16(%r8),%rax cmpl $256,%edx je .L14rounds diff --git a/lib/accelerated/x86/coff/ghash-x86_64.s b/lib/accelerated/x86/coff/ghash-x86_64.s index de207e4002..82634dfa0a 100644 --- a/lib/accelerated/x86/coff/ghash-x86_64.s +++ b/lib/accelerated/x86/coff/ghash-x86_64.s @@ -997,7 +997,7 @@ gcm_ghash_clmul: jz .Lodd_tail movdqu 16(%rdx),%xmm6 - movl _gnutls_x86_cpuid_s+4(%rip),%eax + movl GNUTLS_x86_cpuid_s+4(%rip),%eax cmpq $0x30,%r9 jb .Lskip4x diff --git a/lib/accelerated/x86/coff/sha1-ssse3-x86_64.s b/lib/accelerated/x86/coff/sha1-ssse3-x86_64.s index 79f841f1ac..eb7924d077 100644 --- a/lib/accelerated/x86/coff/sha1-ssse3-x86_64.s +++ b/lib/accelerated/x86/coff/sha1-ssse3-x86_64.s @@ -53,9 +53,9 @@ sha1_block_data_order: movq %r8,%rdx - movl _gnutls_x86_cpuid_s+0(%rip),%r9d - movl _gnutls_x86_cpuid_s+4(%rip),%r8d - movl _gnutls_x86_cpuid_s+8(%rip),%r10d + movl GNUTLS_x86_cpuid_s+0(%rip),%r9d + movl GNUTLS_x86_cpuid_s+4(%rip),%r8d + movl GNUTLS_x86_cpuid_s+8(%rip),%r10d testl $512,%r8d jz .Lialu testl $536870912,%r10d diff --git a/lib/accelerated/x86/coff/sha256-ssse3-x86_64.s b/lib/accelerated/x86/coff/sha256-ssse3-x86_64.s index 78fae2a623..389cac9342 100644 --- a/lib/accelerated/x86/coff/sha256-ssse3-x86_64.s +++ b/lib/accelerated/x86/coff/sha256-ssse3-x86_64.s @@ -53,7 +53,7 @@ sha256_block_data_order: movq %r8,%rdx - leaq _gnutls_x86_cpuid_s(%rip),%r11 + leaq GNUTLS_x86_cpuid_s(%rip),%r11 movl 0(%r11),%r9d movl 4(%r11),%r10d movl 8(%r11),%r11d diff --git a/lib/accelerated/x86/coff/sha512-ssse3-x86_64.s b/lib/accelerated/x86/coff/sha512-ssse3-x86_64.s index 836e0cf66e..8065de24c2 100644 --- a/lib/accelerated/x86/coff/sha512-ssse3-x86_64.s +++ b/lib/accelerated/x86/coff/sha512-ssse3-x86_64.s @@ -53,7 +53,7 @@ sha512_block_data_order: movq %r8,%rdx - leaq _gnutls_x86_cpuid_s(%rip),%r11 + leaq GNUTLS_x86_cpuid_s(%rip),%r11 movl 0(%r11),%r9d movl 4(%r11),%r10d movl 8(%r11),%r11d diff --git a/lib/accelerated/x86/elf/aesni-x86.s b/lib/accelerated/x86/elf/aesni-x86.s index 6e4860209f..0c13b39353 100644 --- a/lib/accelerated/x86/elf/aesni-x86.s +++ b/lib/accelerated/x86/elf/aesni-x86.s @@ -2892,7 +2892,7 @@ _aesni_set_encrypt_key: .L112pic: popl %ebx leal .Lkey_const-.L112pic(%ebx),%ebx - leal _gnutls_x86_cpuid_s-.Lkey_const(%ebx),%ebp + leal GNUTLS_x86_cpuid_s-.Lkey_const(%ebx),%ebp movups (%eax),%xmm0 xorps %xmm4,%xmm4 movl 4(%ebp),%ebp @@ -3273,6 +3273,6 @@ aesni_set_decrypt_key: .byte 83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83 .byte 32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115 .byte 115,108,46,111,114,103,62,0 -.comm _gnutls_x86_cpuid_s,16,4 +.comm GNUTLS_x86_cpuid_s,16,4 .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/elf/aesni-x86_64.s b/lib/accelerated/x86/elf/aesni-x86_64.s index acc7c2c555..b8441980d6 100644 --- a/lib/accelerated/x86/elf/aesni-x86_64.s +++ b/lib/accelerated/x86/elf/aesni-x86_64.s @@ -1151,7 +1151,7 @@ aesni_ctr32_encrypt_blocks: leaq 7(%r8),%r9 movl %r10d,96+12(%rsp) bswapl %r9d - movl _gnutls_x86_cpuid_s+4(%rip),%r10d + movl GNUTLS_x86_cpuid_s+4(%rip),%r10d xorl %ebp,%r9d andl $71303168,%r10d movl %r9d,112+12(%rsp) @@ -3600,7 +3600,7 @@ aesni_cbc_encrypt: movdqa %xmm5,%xmm14 movdqu 80(%rdi),%xmm7 movdqa %xmm6,%xmm15 - movl _gnutls_x86_cpuid_s+4(%rip),%r9d + movl GNUTLS_x86_cpuid_s+4(%rip),%r9d cmpq $0x70,%rdx jbe .Lcbc_dec_six_or_seven @@ -4131,7 +4131,7 @@ __aesni_set_encrypt_key: movl $268437504,%r10d movups (%rdi),%xmm0 xorps %xmm4,%xmm4 - andl _gnutls_x86_cpuid_s+4(%rip),%r10d + andl GNUTLS_x86_cpuid_s+4(%rip),%r10d leaq 16(%rdx),%rax cmpl $256,%esi je .L14rounds diff --git a/lib/accelerated/x86/elf/ghash-x86_64.s b/lib/accelerated/x86/elf/ghash-x86_64.s index 1e4d18b341..856ff179db 100644 --- a/lib/accelerated/x86/elf/ghash-x86_64.s +++ b/lib/accelerated/x86/elf/ghash-x86_64.s @@ -968,7 +968,7 @@ gcm_ghash_clmul: jz .Lodd_tail movdqu 16(%rsi),%xmm6 - movl _gnutls_x86_cpuid_s+4(%rip),%eax + movl GNUTLS_x86_cpuid_s+4(%rip),%eax cmpq $0x30,%rcx jb .Lskip4x diff --git a/lib/accelerated/x86/elf/sha1-ssse3-x86_64.s b/lib/accelerated/x86/elf/sha1-ssse3-x86_64.s index d34f34497c..d85d9ff21b 100644 --- a/lib/accelerated/x86/elf/sha1-ssse3-x86_64.s +++ b/lib/accelerated/x86/elf/sha1-ssse3-x86_64.s @@ -45,9 +45,9 @@ .align 16 sha1_block_data_order: .cfi_startproc - movl _gnutls_x86_cpuid_s+0(%rip),%r9d - movl _gnutls_x86_cpuid_s+4(%rip),%r8d - movl _gnutls_x86_cpuid_s+8(%rip),%r10d + movl GNUTLS_x86_cpuid_s+0(%rip),%r9d + movl GNUTLS_x86_cpuid_s+4(%rip),%r8d + movl GNUTLS_x86_cpuid_s+8(%rip),%r10d testl $512,%r8d jz .Lialu testl $536870912,%r10d diff --git a/lib/accelerated/x86/elf/sha256-ssse3-x86_64.s b/lib/accelerated/x86/elf/sha256-ssse3-x86_64.s index d196c6a793..874062e0df 100644 --- a/lib/accelerated/x86/elf/sha256-ssse3-x86_64.s +++ b/lib/accelerated/x86/elf/sha256-ssse3-x86_64.s @@ -45,7 +45,7 @@ .align 16 sha256_block_data_order: .cfi_startproc - leaq _gnutls_x86_cpuid_s(%rip),%r11 + leaq GNUTLS_x86_cpuid_s(%rip),%r11 movl 0(%r11),%r9d movl 4(%r11),%r10d movl 8(%r11),%r11d diff --git a/lib/accelerated/x86/elf/sha512-ssse3-x86_64.s b/lib/accelerated/x86/elf/sha512-ssse3-x86_64.s index 446c06a3e6..039b1d7dd2 100644 --- a/lib/accelerated/x86/elf/sha512-ssse3-x86_64.s +++ b/lib/accelerated/x86/elf/sha512-ssse3-x86_64.s @@ -45,7 +45,7 @@ .align 16 sha512_block_data_order: .cfi_startproc - leaq _gnutls_x86_cpuid_s(%rip),%r11 + leaq GNUTLS_x86_cpuid_s(%rip),%r11 movl 0(%r11),%r9d movl 4(%r11),%r10d movl 8(%r11),%r11d diff --git a/lib/accelerated/x86/macosx/aesni-x86.s b/lib/accelerated/x86/macosx/aesni-x86.s index ee50089146..774d1f4a01 100644 --- a/lib/accelerated/x86/macosx/aesni-x86.s +++ b/lib/accelerated/x86/macosx/aesni-x86.s @@ -2853,7 +2853,7 @@ __aesni_set_encrypt_key: L112pic: popl %ebx leal Lkey_const-L112pic(%ebx),%ebx - movl L__gnutls_x86_cpuid_s$non_lazy_ptr-Lkey_const(%ebx),%ebp + movl L_GNUTLS_x86_cpuid_s$non_lazy_ptr-Lkey_const(%ebx),%ebp movups (%eax),%xmm0 xorps %xmm4,%xmm4 movl 4(%ebp),%ebp @@ -3230,8 +3230,8 @@ Lkey_const: .byte 32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115 .byte 115,108,46,111,114,103,62,0 .section __IMPORT,__pointers,non_lazy_symbol_pointers -L__gnutls_x86_cpuid_s$non_lazy_ptr: -.indirect_symbol __gnutls_x86_cpuid_s +L_GNUTLS_x86_cpuid_s$non_lazy_ptr: +.indirect_symbol _GNUTLS_x86_cpuid_s .long 0 -.comm __gnutls_x86_cpuid_s,16,2 +.comm _GNUTLS_x86_cpuid_s,16,2 diff --git a/lib/accelerated/x86/macosx/aesni-x86_64.s b/lib/accelerated/x86/macosx/aesni-x86_64.s index 3601d54386..afb7aeac9f 100644 --- a/lib/accelerated/x86/macosx/aesni-x86_64.s +++ b/lib/accelerated/x86/macosx/aesni-x86_64.s @@ -1151,7 +1151,7 @@ L$ctr32_bulk: leaq 7(%r8),%r9 movl %r10d,96+12(%rsp) bswapl %r9d - movl __gnutls_x86_cpuid_s+4(%rip),%r10d + movl _GNUTLS_x86_cpuid_s+4(%rip),%r10d xorl %ebp,%r9d andl $71303168,%r10d movl %r9d,112+12(%rsp) @@ -3590,7 +3590,7 @@ L$cbc_decrypt_bulk: movdqa %xmm5,%xmm14 movdqu 80(%rdi),%xmm7 movdqa %xmm6,%xmm15 - movl __gnutls_x86_cpuid_s+4(%rip),%r9d + movl _GNUTLS_x86_cpuid_s+4(%rip),%r9d cmpq $0x70,%rdx jbe L$cbc_dec_six_or_seven @@ -4121,7 +4121,7 @@ __aesni_set_encrypt_key: movl $268437504,%r10d movups (%rdi),%xmm0 xorps %xmm4,%xmm4 - andl __gnutls_x86_cpuid_s+4(%rip),%r10d + andl _GNUTLS_x86_cpuid_s+4(%rip),%r10d leaq 16(%rdx),%rax cmpl $256,%esi je L$14rounds diff --git a/lib/accelerated/x86/macosx/ghash-x86_64.s b/lib/accelerated/x86/macosx/ghash-x86_64.s index 5fd3216755..a715212393 100644 --- a/lib/accelerated/x86/macosx/ghash-x86_64.s +++ b/lib/accelerated/x86/macosx/ghash-x86_64.s @@ -956,7 +956,7 @@ L$_ghash_clmul: jz L$odd_tail movdqu 16(%rsi),%xmm6 - movl __gnutls_x86_cpuid_s+4(%rip),%eax + movl _GNUTLS_x86_cpuid_s+4(%rip),%eax cmpq $0x30,%rcx jb L$skip4x diff --git a/lib/accelerated/x86/macosx/sha1-ssse3-x86_64.s b/lib/accelerated/x86/macosx/sha1-ssse3-x86_64.s index 7b5d9dfc9e..f326c34e60 100644 --- a/lib/accelerated/x86/macosx/sha1-ssse3-x86_64.s +++ b/lib/accelerated/x86/macosx/sha1-ssse3-x86_64.s @@ -45,9 +45,9 @@ .p2align 4 _sha1_block_data_order: - movl __gnutls_x86_cpuid_s+0(%rip),%r9d - movl __gnutls_x86_cpuid_s+4(%rip),%r8d - movl __gnutls_x86_cpuid_s+8(%rip),%r10d + movl _GNUTLS_x86_cpuid_s+0(%rip),%r9d + movl _GNUTLS_x86_cpuid_s+4(%rip),%r8d + movl _GNUTLS_x86_cpuid_s+8(%rip),%r10d testl $512,%r8d jz L$ialu testl $536870912,%r10d diff --git a/lib/accelerated/x86/macosx/sha256-ssse3-x86_64.s b/lib/accelerated/x86/macosx/sha256-ssse3-x86_64.s index 9fed36b9c8..1312ef49ec 100644 --- a/lib/accelerated/x86/macosx/sha256-ssse3-x86_64.s +++ b/lib/accelerated/x86/macosx/sha256-ssse3-x86_64.s @@ -45,7 +45,7 @@ .p2align 4 _sha256_block_data_order: - leaq __gnutls_x86_cpuid_s(%rip),%r11 + leaq _GNUTLS_x86_cpuid_s(%rip),%r11 movl 0(%r11),%r9d movl 4(%r11),%r10d movl 8(%r11),%r11d diff --git a/lib/accelerated/x86/macosx/sha512-ssse3-x86_64.s b/lib/accelerated/x86/macosx/sha512-ssse3-x86_64.s index e78d90f2d3..6e52aaaaa7 100644 --- a/lib/accelerated/x86/macosx/sha512-ssse3-x86_64.s +++ b/lib/accelerated/x86/macosx/sha512-ssse3-x86_64.s @@ -45,7 +45,7 @@ .p2align 4 _sha512_block_data_order: - leaq __gnutls_x86_cpuid_s(%rip),%r11 + leaq _GNUTLS_x86_cpuid_s(%rip),%r11 movl 0(%r11),%r9d movl 4(%r11),%r10d movl 8(%r11),%r11d diff --git a/lib/accelerated/x86/x86-common.c b/lib/accelerated/x86/x86-common.c index b2bbf7f2fa..147801d09d 100644 --- a/lib/accelerated/x86/x86-common.c +++ b/lib/accelerated/x86/x86-common.c @@ -82,7 +82,7 @@ __attribute__((visibility("hidden"))) #elif defined(__SUNPRO_C) __hidden #endif -unsigned int _gnutls_x86_cpuid_s[4]; +unsigned int GNUTLS_x86_cpuid_s[4]; #ifndef bit_SHA # define bit_SHA (1<<29) @@ -110,6 +110,26 @@ unsigned int _gnutls_x86_cpuid_s[4]; # define bit_AVX 0x10000000 #endif +#ifndef bit_AVX2 +# define bit_AVX2 0x00000020 +#endif + +#ifndef bit_AVX512F +# define bit_AVX512F 0x00010000 +#endif + +#ifndef bit_AVX512IFMA +# define bit_AVX512IFMA 0x00200000 +#endif + +#ifndef bit_AVX512BW +# define bit_AVX512BW 0x40000000 +#endif + +#ifndef bit_AVX512VL +# define bit_AVX512VL 0x80000000 +#endif + #ifndef bit_OSXSAVE # define bit_OSXSAVE 0x8000000 #endif @@ -118,10 +138,6 @@ unsigned int _gnutls_x86_cpuid_s[4]; # define bit_MOVBE 0x00400000 #endif -#ifndef OSXSAVE_MASK -# define OSXSAVE_MASK (bit_OSXSAVE|bit_MOVBE) -#endif - #define bit_PADLOCK (0x3 << 6) #define bit_PADLOCK_PHE (0x3 << 10) #define bit_PADLOCK_PHE_SHA512 (0x3 << 25) @@ -177,7 +193,7 @@ static unsigned check_4th_gen_intel_features(unsigned ecx) { uint32_t xcr0; - if ((ecx & OSXSAVE_MASK) != OSXSAVE_MASK) + if ((ecx & bit_OSXSAVE) != bit_OSXSAVE) return 0; #if defined(_MSC_VER) && !defined(__clang__) @@ -202,7 +218,7 @@ static void capabilities_to_intel_cpuid(unsigned capabilities) if (capabilities & INTEL_AES_NI) { if (a[1] & bit_AES) { - _gnutls_x86_cpuid_s[1] |= bit_AES; + GNUTLS_x86_cpuid_s[1] |= bit_AES; } else { _gnutls_debug_log ("AESNI acceleration requested but not available\n"); @@ -211,7 +227,7 @@ static void capabilities_to_intel_cpuid(unsigned capabilities) if (capabilities & INTEL_SSSE3) { if (a[1] & bit_SSSE3) { - _gnutls_x86_cpuid_s[1] |= bit_SSSE3; + GNUTLS_x86_cpuid_s[1] |= bit_SSSE3; } else { _gnutls_debug_log ("SSSE3 acceleration requested but not available\n"); @@ -219,8 +235,9 @@ static void capabilities_to_intel_cpuid(unsigned capabilities) } if (capabilities & INTEL_AVX) { - if ((a[1] & bit_AVX) && check_4th_gen_intel_features(a[1])) { - _gnutls_x86_cpuid_s[1] |= bit_AVX|OSXSAVE_MASK; + if ((a[1] & bit_AVX) && (a[1] & bit_MOVBE) && + check_4th_gen_intel_features(a[1])) { + GNUTLS_x86_cpuid_s[1] |= bit_AVX|bit_MOVBE; } else { _gnutls_debug_log ("AVX acceleration requested but not available\n"); @@ -229,7 +246,7 @@ static void capabilities_to_intel_cpuid(unsigned capabilities) if (capabilities & INTEL_PCLMUL) { if (a[1] & bit_PCLMUL) { - _gnutls_x86_cpuid_s[1] |= bit_PCLMUL; + GNUTLS_x86_cpuid_s[1] |= bit_PCLMUL; } else { _gnutls_debug_log ("PCLMUL acceleration requested but not available\n"); @@ -238,7 +255,7 @@ static void capabilities_to_intel_cpuid(unsigned capabilities) if (capabilities & INTEL_SHA) { if (a[2] & bit_SHA) { - _gnutls_x86_cpuid_s[2] |= bit_SHA; + GNUTLS_x86_cpuid_s[2] |= bit_SHA; } else { _gnutls_debug_log ("SHA acceleration requested but not available\n"); @@ -249,31 +266,28 @@ static void capabilities_to_intel_cpuid(unsigned capabilities) static unsigned check_optimized_aes(void) { - return (_gnutls_x86_cpuid_s[1] & bit_AES); + return (GNUTLS_x86_cpuid_s[1] & bit_AES); } static unsigned check_ssse3(void) { - return (_gnutls_x86_cpuid_s[1] & bit_SSSE3); + return (GNUTLS_x86_cpuid_s[1] & bit_SSSE3); } static unsigned check_sha(void) { - return (_gnutls_x86_cpuid_s[2] & bit_SHA); + return (GNUTLS_x86_cpuid_s[2] & bit_SHA); } #ifdef ASM_X86_64 static unsigned check_avx_movbe(void) { - if (check_4th_gen_intel_features(_gnutls_x86_cpuid_s[1]) == 0) - return 0; - - return ((_gnutls_x86_cpuid_s[1] & bit_AVX)); + return (GNUTLS_x86_cpuid_s[1] & (bit_AVX|bit_MOVBE)) == (bit_AVX|bit_MOVBE); } static unsigned check_pclmul(void) { - return (_gnutls_x86_cpuid_s[1] & bit_PCLMUL); + return (GNUTLS_x86_cpuid_s[1] & bit_PCLMUL); } #endif @@ -290,7 +304,7 @@ static unsigned capabilities_to_zhaoxin_edx(unsigned capabilities) return 0; if (capabilities & PADLOCK) { if (c & bit_PADLOCK) { - _gnutls_x86_cpuid_s[2] |= bit_PADLOCK; + GNUTLS_x86_cpuid_s[2] |= bit_PADLOCK; } else { _gnutls_debug_log ("Padlock acceleration requested but not available\n"); @@ -299,7 +313,7 @@ static unsigned capabilities_to_zhaoxin_edx(unsigned capabilities) if (capabilities & PADLOCK_PHE) { if (c & bit_PADLOCK_PHE) { - _gnutls_x86_cpuid_s[2] |= bit_PADLOCK_PHE; + GNUTLS_x86_cpuid_s[2] |= bit_PADLOCK_PHE; } else { _gnutls_debug_log ("Padlock-PHE acceleration requested but not available\n"); @@ -308,14 +322,14 @@ static unsigned capabilities_to_zhaoxin_edx(unsigned capabilities) if (capabilities & PADLOCK_PHE_SHA512) { if (c & bit_PADLOCK_PHE_SHA512) { - _gnutls_x86_cpuid_s[2] |= bit_PADLOCK_PHE_SHA512; + GNUTLS_x86_cpuid_s[2] |= bit_PADLOCK_PHE_SHA512; } else { _gnutls_debug_log ("Padlock-PHE-SHA512 acceleration requested but not available\n"); } } - return _gnutls_x86_cpuid_s[2]; + return GNUTLS_x86_cpuid_s[2]; } static int check_padlock(unsigned edx) @@ -403,10 +417,10 @@ void register_x86_padlock_crypto(unsigned capabilities) if (check_zhaoxin() == 0) return; - memset(_gnutls_x86_cpuid_s, 0, sizeof(_gnutls_x86_cpuid_s)); + memset(GNUTLS_x86_cpuid_s, 0, sizeof(GNUTLS_x86_cpuid_s)); if (capabilities == 0){ - if(!read_cpuid_vals(_gnutls_x86_cpuid_s)) + if(!read_cpuid_vals(GNUTLS_x86_cpuid_s)) return; edx = padlock_capability(); } else{ @@ -903,7 +917,7 @@ void register_x86_intel_crypto(unsigned capabilities) int ret; enum x86_cpu_vendor vendor; - memset(_gnutls_x86_cpuid_s, 0, sizeof(_gnutls_x86_cpuid_s)); + memset(GNUTLS_x86_cpuid_s, 0, sizeof(GNUTLS_x86_cpuid_s)); vendor = check_x86_cpu_vendor(); if (vendor == X86_CPU_VENDOR_OTHER) { @@ -911,17 +925,30 @@ void register_x86_intel_crypto(unsigned capabilities) } if (capabilities == 0) { - if (!read_cpuid_vals(_gnutls_x86_cpuid_s)) + if (!read_cpuid_vals(GNUTLS_x86_cpuid_s)) return; + if (!check_4th_gen_intel_features(GNUTLS_x86_cpuid_s[1])) { + GNUTLS_x86_cpuid_s[1] &= ~bit_AVX; + + /* Clear AVX2 bits as well, according to what + * OpenSSL does. Should we clear + * bit_AVX512DQ, bit_AVX512PF, bit_AVX512ER, + * and bit_AVX512CD? */ + GNUTLS_x86_cpuid_s[2] &= ~(bit_AVX2| + bit_AVX512F| + bit_AVX512IFMA| + bit_AVX512BW| + bit_AVX512BW); + } } else { capabilities_to_intel_cpuid(capabilities); } /* CRYPTOGAMS uses the (1 << 30) bit as an indicator of Intel CPUs */ if (vendor == X86_CPU_VENDOR_INTEL) { - _gnutls_x86_cpuid_s[0] |= 1 << 30; + GNUTLS_x86_cpuid_s[0] |= 1 << 30; } else { - _gnutls_x86_cpuid_s[0] &= ~(1 << 30); + GNUTLS_x86_cpuid_s[0] &= ~(1 << 30); } if (check_ssse3()) { diff --git a/lib/algorithms.h b/lib/algorithms.h index da72403fba..2c33a7210f 100644 --- a/lib/algorithms.h +++ b/lib/algorithms.h @@ -354,13 +354,18 @@ const gnutls_protocol_t *_gnutls_protocol_list(void); int _gnutls_version_mark_disabled(gnutls_protocol_t version); gnutls_protocol_t _gnutls_protocol_get_id_if_supported(const char *name); +int _gnutls_digest_set_secure(gnutls_digest_algorithm_t dig, unsigned int secure); +int _gnutls_sign_set_secure(gnutls_sign_algorithm_t sign, hash_security_level_t slevel); +int _gnutls_protocol_set_enabled(gnutls_protocol_t version, unsigned int enabled); +int _gnutls_ecc_curve_set_enabled(gnutls_ecc_curve_t curve, unsigned int enabled); + /* these functions are for revertible settings, meaning that algorithms marked * as disabled/insecure with mark_*_all functions can be re-enabled with * mark_{enabled,secure} functions */ void _gnutls_ecc_curve_mark_disabled_all(void); +void _gnutls_version_mark_disabled_all(void); void _gnutls_sign_mark_insecure_all(hash_security_level_t level); void _gnutls_digest_mark_insecure_all(void); -void _gnutls_version_mark_revertible_all(void); #define GNUTLS_SIGN_FLAG_TLS13_OK 1 /* if it is ok to use under TLS1.3 */ #define GNUTLS_SIGN_FLAG_CRT_VRFY_REVERSE (1 << 1) /* reverse order of bytes in CrtVrfy signature */ diff --git a/lib/algorithms/ecc.c b/lib/algorithms/ecc.c index 52ae1db0e4..303a42612f 100644 --- a/lib/algorithms/ecc.c +++ b/lib/algorithms/ecc.c @@ -379,26 +379,8 @@ void _gnutls_ecc_curve_mark_disabled_all(void) } } -/** - * gnutls_ecc_curve_set_enabled: - * @curve: is an ECC curve - * @enabled: whether to enable the curve - * - * Modify the previous system wide setting that marked @curve as - * enabled or disabled. This only has effect when the curve is - * enabled through the allowlisting mode in the configuration file, or - * when the setting is modified with a prior call to this function. - * - * This function must be called prior to any session priority setting functions; - * otherwise the behavior is undefined. - * - * Returns: 0 on success or negative error code otherwise. - * - * Since: 3.7.3 - */ int -gnutls_ecc_curve_set_enabled(gnutls_ecc_curve_t curve, - unsigned int enabled) +_gnutls_ecc_curve_set_enabled(gnutls_ecc_curve_t curve, unsigned int enabled) { gnutls_ecc_curve_entry_st *p; diff --git a/lib/algorithms/mac.c b/lib/algorithms/mac.c index 166d51d552..47fbc226bd 100644 --- a/lib/algorithms/mac.c +++ b/lib/algorithms/mac.c @@ -322,24 +322,8 @@ void _gnutls_digest_mark_insecure_all(void) #endif } -/** - * gnutls_digest_set_secure: - * @dig: is a digest algorithm - * @secure: whether to mark the digest algorithm secure - * - * Modify the previous system wide setting that marked @dig as secure - * or insecure. This only has effect when the algorithm is enabled - * through the allowlisting mode in the configuration file, or when - * the setting is modified with a prior call to this function. - * - * This function must be called prior to any session priority setting functions; - * otherwise the behavior is undefined. - * - * Since: 3.7.3 - */ int -gnutls_digest_set_secure(gnutls_digest_algorithm_t dig, - unsigned int secure) +_gnutls_digest_set_secure(gnutls_digest_algorithm_t dig, unsigned int secure) { #ifndef DISABLE_SYSTEM_CONFIG mac_entry_st *p; diff --git a/lib/algorithms/protocols.c b/lib/algorithms/protocols.c index 3006e8242d..a4fd4837cd 100644 --- a/lib/algorithms/protocols.c +++ b/lib/algorithms/protocols.c @@ -192,10 +192,11 @@ static int version_is_valid_for_session(gnutls_session_t session, const version_entry_st *v) { - if (v->supported && v->transport == session->internals.transport) { - return 1; - } - return 0; + if (!v->supported && !(v->supported_revertible && _gnutls_allowlisting_mode())) + return 0; + if (v->transport != session->internals.transport) + return 0; + return 1; } /* This is only called by cfg_apply in priority.c, in blocklisting mode. */ @@ -215,37 +216,20 @@ int _gnutls_version_mark_disabled(gnutls_protocol_t version) } /* This is only called by cfg_apply in priority.c, in allowlisting mode. */ -void _gnutls_version_mark_revertible_all(void) +void _gnutls_version_mark_disabled_all(void) { #ifndef DISABLE_SYSTEM_CONFIG version_entry_st *p; for (p = sup_versions; p->name != NULL; p++) { + p->supported = false; p->supported_revertible = true; } - #endif } -/** - * gnutls_protocol_set_enabled: - * @version: is a (gnutls) version number - * @enabled: whether to enable the protocol - * - * Mark the previous system wide setting that marked @version as - * enabled or disabled. This only has effect when the version is - * enabled through the allowlisting mode in the configuration file, or - * when the setting is modified with a prior call to this function. - * - * This function must be called prior to any session priority setting functions; - * otherwise the behavior is undefined. - * - * Returns: 0 on success or negative error code otherwise. - * - * Since: 3.7.3 - */ int -gnutls_protocol_set_enabled(gnutls_protocol_t version, +_gnutls_protocol_set_enabled(gnutls_protocol_t version, unsigned int enabled) { #ifndef DISABLE_SYSTEM_CONFIG @@ -336,7 +320,10 @@ const version_entry_st *_gnutls_version_max(gnutls_session_t session) if (p->obsolete != 0) break; #endif - if (!p->supported || p->transport != session->internals.transport) + if (!p->supported && !(p->supported_revertible && _gnutls_allowlisting_mode())) + break; + + if (p->transport != session->internals.transport) break; if (p->tls13_sem && (session->internals.flags & INT_FLAG_NO_TLS13)) @@ -391,7 +378,10 @@ int _gnutls_write_supported_versions(gnutls_session_t session, uint8_t *buffer, if (p->obsolete != 0) break; - if (!p->supported || p->transport != session->internals.transport) + if (!p->supported && !(p->supported_revertible && _gnutls_allowlisting_mode())) + break; + + if (p->transport != session->internals.transport) break; if (p->only_extension) @@ -574,7 +564,10 @@ _gnutls_nversion_is_supported(gnutls_session_t session, if (p->tls13_sem && (session->internals.flags & INT_FLAG_NO_TLS13)) return 0; - if (!p->supported || p->transport != session->internals.transport) + if (!p->supported && !(p->supported_revertible && _gnutls_allowlisting_mode())) + return 0; + + if (p->transport != session->internals.transport) return 0; version = p->id; diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c index 4a5aaa75e1..06e2839631 100644 --- a/lib/algorithms/sign.c +++ b/lib/algorithms/sign.c @@ -503,28 +503,9 @@ void _gnutls_sign_mark_insecure_all(hash_security_level_t level) #endif } -/** - * gnutls_sign_set_secure: - * @sign: the sign algorithm - * @secure: whether to mark the sign algorithm secure - * - * Modify the previous system wide setting that marked @sign as secure - * or insecure. This only has effect when the algorithm is marked as - * secure through the allowlisting mode in the configuration file, or - * when the setting is modified with a prior call to this function. - * - * Even when @secure is true, @sign is not marked as secure for the - * use in certificates. Use gnutls_sign_set_secure_for_certs() to - * mark it secure as well for certificates. - * - * This function must be called prior to any session priority setting functions; - * otherwise the behavior is undefined. - * - * Since: 3.7.3 - */ int -gnutls_sign_set_secure(gnutls_sign_algorithm_t sign, - unsigned int secure) +_gnutls_sign_set_secure(gnutls_sign_algorithm_t sign, + hash_security_level_t slevel) { #ifndef DISABLE_SYSTEM_CONFIG gnutls_sign_entry_st *p; @@ -534,60 +515,7 @@ gnutls_sign_set_secure(gnutls_sign_algorithm_t sign, if (!(p->flags & GNUTLS_SIGN_FLAG_INSECURE_REVERTIBLE)) { return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } - if (secure) { - if (p->slevel > _INSECURE_FOR_CERTS) { - p->slevel = _INSECURE_FOR_CERTS; - } - } else { - p->slevel = _INSECURE; - } - return 0; - } - } -#endif - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); -} - -/** - * gnutls_sign_set_secure_for_certs: - * @sign: the sign algorithm - * @secure: whether to mark the sign algorithm secure for certificates - * - * Modify the previous system wide setting that marked @sign as secure - * or insecure for the use in certificates. This only has effect when - * the algorithm is marked as secure through the allowlisting mode in - * the configuration file, or when the setting is modified with a - * prior call to this function. - * - * When @secure is true, @sign is marked as secure for any use unlike - * gnutls_sign_set_secure(). Otherwise, it is marked as insecure only - * for the use in certificates. Use gnutls_sign_set_secure() to mark - * it insecure for any uses. - * - * This function must be called prior to any session priority setting functions; - * otherwise the behavior is undefined. - * - * Since: 3.7.3 - */ -int -gnutls_sign_set_secure_for_certs(gnutls_sign_algorithm_t sign, - unsigned int secure) -{ -#ifndef DISABLE_SYSTEM_CONFIG - gnutls_sign_entry_st *p; - - for(p = sign_algorithms; p->name != NULL; p++) { - if (p->id && p->id == sign) { - if (!(p->flags & GNUTLS_SIGN_FLAG_INSECURE_REVERTIBLE)) { - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - } - if (secure) { - p->slevel = _SECURE; - } else { - if (p->slevel < _INSECURE_FOR_CERTS) { - p->slevel = _INSECURE_FOR_CERTS; - } - } + p->slevel = slevel; return 0; } } diff --git a/lib/ext/compress_certificate.c b/lib/ext/compress_certificate.c index 8144368faa..8f8d75c9ad 100644 --- a/lib/ext/compress_certificate.c +++ b/lib/ext/compress_certificate.c @@ -161,7 +161,7 @@ gnutls_compress_certificate_set_methods(gnutls_session_t session, return 0; } -static int +int _gnutls_compress_certificate_recv_params(gnutls_session_t session, const uint8_t * data, size_t data_size) @@ -209,7 +209,7 @@ _gnutls_compress_certificate_recv_params(gnutls_session_t session, return 0; } -static int +int _gnutls_compress_certificate_send_params(gnutls_session_t session, gnutls_buffer_st * data) { @@ -245,7 +245,7 @@ const hello_ext_entry_st ext_mod_compress_certificate = { .client_parse_point = GNUTLS_EXT_TLS, .server_parse_point = GNUTLS_EXT_TLS, .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | - GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO, + GNUTLS_EXT_FLAG_CLIENT_HELLO, .recv_func = _gnutls_compress_certificate_recv_params, .send_func = _gnutls_compress_certificate_send_params, .deinit_func = _gnutls_hello_ext_default_deinit diff --git a/lib/ext/compress_certificate.h b/lib/ext/compress_certificate.h index 88199da187..b7083742ef 100644 --- a/lib/ext/compress_certificate.h +++ b/lib/ext/compress_certificate.h @@ -38,4 +38,12 @@ extern const hello_ext_entry_st ext_mod_compress_certificate; gnutls_compression_method_t _gnutls_compress_certificate_num2method(uint16_t num); int _gnutls_compress_certificate_method2num(gnutls_compression_method_t method); +int +_gnutls_compress_certificate_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +int +_gnutls_compress_certificate_send_params(gnutls_session_t session, + gnutls_buffer_st * data); + #endif /* GNUTLS_LIB_EXT_COMPRESS_CERTIFICATE_H */ diff --git a/lib/fips.c b/lib/fips.c index 7d143e608e..54eb4a37d4 100644 --- a/lib/fips.c +++ b/lib/fips.c @@ -440,11 +440,6 @@ int _gnutls_fips_perform_self_checks2(void) /* Tests the FIPS algorithms */ /* ciphers - one test per cipher */ - ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_3DES_CBC); - if (ret < 0) { - return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); - } - ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_CBC); if (ret < 0) { return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); diff --git a/lib/global.c b/lib/global.c index a77ea054f5..abf3d7fd1a 100644 --- a/lib/global.c +++ b/lib/global.c @@ -574,6 +574,7 @@ static const struct gnutls_library_config_st _gnutls_library_config[] = { { "libgmp-soname", GMP_LIBRARY_SONAME }, { "hardware-features", HW_FEATURES }, { "tls-features", TLS_FEATURES }, + { "default-system-config", SYSTEM_PRIORITY_FILE }, { NULL, NULL } }; diff --git a/lib/global.h b/lib/global.h index 16fde08b5c..6bd70df8e3 100644 --- a/lib/global.h +++ b/lib/global.h @@ -48,5 +48,6 @@ extern void _gnutls_nss_keylog_deinit(void); extern void _gnutls_prepare_to_load_system_priorities(void); extern void _gnutls_unload_system_priorities(void); +extern bool _gnutls_allowlisting_mode(void); #endif /* GNUTLS_LIB_GLOBAL_H */ diff --git a/lib/handshake.c b/lib/handshake.c index cf025a84f6..21edc5ece9 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -2861,7 +2861,8 @@ int gnutls_handshake(gnutls_session_t session) #ifdef ENABLE_KTLS if (_gnutls_config_is_ktls_enabled()) { - if (session->internals.pull_func || + if ((session->internals.pull_func && + session->internals.pull_func != system_read) || session->internals.push_func) { _gnutls_audit_log(session, "Not enabling KTLS with " diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index bbf932f60f..779523ced3 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1175,7 +1175,7 @@ typedef enum { * gnutls_channel_binding_t: * @GNUTLS_CB_TLS_UNIQUE: "tls-unique" (RFC 5929) channel binding * @GNUTLS_CB_TLS_SERVER_END_POINT: "tls-server-end-point" (RFC 5929) channel binding - * @GNUTLS_CB_TLS_EXPORTER: "tls-exporter" (draft-ietf-kitten-tls-channel-bindings-for-tls13-03) + * @GNUTLS_CB_TLS_EXPORTER: "tls-exporter" (RFC 9266) channel binding * * Enumeration of supported channel binding types. */ diff --git a/lib/nettle/cipher.c b/lib/nettle/cipher.c index b41862d1ea..c9c59fb0ba 100644 --- a/lib/nettle/cipher.c +++ b/lib/nettle/cipher.c @@ -1096,7 +1096,7 @@ wrap_nettle_cipher_init(gnutls_cipher_algorithm_t algo, void **_ctx, int enc) { struct nettle_cipher_ctx *ctx; - ptrdiff_t cur_alignment; + uintptr_t cur_alignment; int idx = -1; unsigned i; uint8_t *ctx_ptr; @@ -1120,7 +1120,7 @@ wrap_nettle_cipher_init(gnutls_cipher_algorithm_t algo, void **_ctx, ctx->enc = enc; ctx_ptr = ((uint8_t*)ctx) + sizeof(*ctx); - cur_alignment = ((ptrdiff_t)ctx_ptr) % 16; + cur_alignment = ((uintptr_t)ctx_ptr) % 16; if (cur_alignment > 0) ctx_ptr += 16 - cur_alignment; diff --git a/lib/nettle/init.c b/lib/nettle/init.c index d06faf941e..9cd6b1486b 100644 --- a/lib/nettle/init.c +++ b/lib/nettle/init.c @@ -30,14 +30,15 @@ static void gnutls_free_zero(void *data, size_t size); static void *gnutls_realloc_zero(void *data, size_t old_size, size_t new_size); +static void *(*allocfunc) (size_t); +static void *(*reallocfunc) (void *, size_t, size_t); +static void (*freefunc) (void *, size_t); + /* Functions that refer to the initialization of the nettle library. */ int gnutls_crypto_init(void) { - void *(*allocfunc) (size_t); - void *(*reallocfunc) (void *, size_t, size_t); - void (*freefunc) (void *, size_t); void *(*defallocfunc) (size_t); void *(*defreallocfunc) (void *, size_t, size_t); void (*deffreefunc) (void *, size_t); @@ -65,6 +66,7 @@ int gnutls_crypto_init(void) void gnutls_crypto_deinit(void) { + mp_set_memory_functions(allocfunc, reallocfunc, freefunc); } /*- diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index eba246f0b3..f38016b19a 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -1247,20 +1247,20 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, _rsa_params_to_privkey(pk_params, &priv); - /* RSA key size should be 2048-bit or larger in FIPS - * 140-3. In addition to this, only SHA-2 is allowed - * for SigGen; it is checked in pk_prepare_hash lib/pk.c - */ - if (unlikely(priv.size < 256)) { - not_approved = true; - } - ret = _rsa_params_to_pubkey(pk_params, &pub); if (ret < 0) { gnutls_assert(); goto cleanup; } + /* RSA modulus size should be 2048-bit or larger in FIPS + * 140-3. In addition to this, only SHA-2 is allowed + * for SigGen; it is checked in pk_prepare_hash lib/pk.c + */ + if (unlikely(mpz_sizeinbase(pub.n, 2) < 2048)) { + not_approved = true; + } + mpz_init(s); if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST) @@ -1298,22 +1298,22 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, _rsa_params_to_privkey(pk_params, &priv); - /* RSA key size should be 2048-bit or larger in FIPS + ret = _rsa_params_to_pubkey(pk_params, &pub); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* RSA modulus size should be 2048-bit or larger in FIPS * 140-3. In addition to this, only SHA-2 is allowed * for SigGen; however, Nettle only support SHA256, * SHA384, and SHA512 for RSA-PSS (see * _rsa_pss_sign_digest_tr in this file for details). */ - if (unlikely(priv.size < 256)) { + if (unlikely(mpz_sizeinbase(pub.n, 2) < 2048)) { not_approved = true; } - ret = _rsa_params_to_pubkey(pk_params, &pub); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - mpz_init(s); ret = @@ -1643,6 +1643,7 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo, case GNUTLS_PK_RSA: { struct rsa_public_key pub; + size_t bits; ret = _rsa_params_to_pubkey(pk_params, &pub); if (ret < 0) { @@ -1650,12 +1651,19 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo, goto cleanup; } - /* RSA key size should be 2048-bit or larger in FIPS - * 140-3. In addition to this, only SHA-1 and SHA-2 are - * allowed for SigVer; it is checked in - * _pkcs1_rsa_verify_sig in lib/pubkey.c + bits = mpz_sizeinbase(pub.n, 2); + + /* In FIPS 140-3, RSA key size should be larger than + * 2048-bit or one of the known lengths (1024, 1280, + * 1536, 1792; i.e., multiple of 256-bits). + * + * In addition to this, only SHA-1 and SHA-2 are allowed + * for SigVer; it is checked in _pkcs1_rsa_verify_sig in + * lib/pubkey.c. */ - if (unlikely(pub.size < 256)) { + if (unlikely(bits < 2048 && + bits != 1024 && bits != 1280 && + bits != 1536 && bits != 1792)) { not_approved = true; } @@ -1701,13 +1709,13 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo, goto cleanup; } - /* RSA key size should be 2048-bit or larger in FIPS + /* RSA modulus size should be 2048-bit or larger in FIPS * 140-3. In addition to this, only SHA-1 and SHA-2 are * allowed for SigVer, while Nettle only supports * SHA256, SHA384, and SHA512 for RSA-PSS (see * _rsa_pss_verify_digest in this file for the details). */ - if (unlikely(pub.size < 256)) { + if (unlikely(mpz_sizeinbase(pub.n, 2) < 2048)) { not_approved = true; } diff --git a/lib/priority.c b/lib/priority.c index d163d8169f..efa4d909b0 100644 --- a/lib/priority.c +++ b/lib/priority.c @@ -1040,6 +1040,10 @@ struct cfg { gnutls_kx_algorithm_t kxs[MAX_ALGOS+1]; gnutls_sign_algorithm_t sigs[MAX_ALGOS+1]; gnutls_protocol_t versions[MAX_ALGOS+1]; + + gnutls_digest_algorithm_t hashes[MAX_ALGOS+1]; + gnutls_ecc_curve_t ecc_curves[MAX_ALGOS+1]; + gnutls_sign_algorithm_t sigs_for_cert[MAX_ALGOS+1]; }; static inline void @@ -1066,6 +1070,11 @@ static unsigned system_priority_file_loaded = 0; #define OVERRIDES_SECTION "overrides" #define MAX_ALGO_NAME 2048 +bool _gnutls_allowlisting_mode(void) +{ + return system_wide_config.allowlisting; +} + static void _clear_default_system_priority(void) { gnutls_free(system_wide_config.default_priority_string); @@ -1145,12 +1154,296 @@ cfg_steal(struct cfg *dst, struct cfg *src) memcpy(dst->macs, src->macs, sizeof(src->macs)); memcpy(dst->groups, src->groups, sizeof(src->groups)); memcpy(dst->kxs, src->kxs, sizeof(src->kxs)); + memcpy(dst->hashes, src->hashes, sizeof(src->hashes)); + memcpy(dst->ecc_curves, src->ecc_curves, sizeof(src->ecc_curves)); + memcpy(dst->sigs, src->sigs, sizeof(src->sigs)); + memcpy(dst->sigs_for_cert, src->sigs_for_cert, + sizeof(src->sigs_for_cert)); +} + +/* + * synchronizing changes from struct cfg to global `lib/algorithms` arrays + */ + +/* global side-effect! modifies `flags` in `hash_algorithms[]` */ +static inline int /* allowlisting-only */ +_cfg_hashes_remark(struct cfg* cfg) +{ + size_t i; + _gnutls_digest_mark_insecure_all(); + for (i = 0; cfg->hashes[i] != 0; i++) { + int ret = _gnutls_digest_set_secure(cfg->hashes[i], 1); + if (unlikely(ret < 0)) { + return gnutls_assert_val(ret); + } + } + return 0; +} + +/* global side-effect! modifies `flags` in `sign_algorithms[]` */ +static inline int /* allowlisting-only */ +_cfg_sigs_remark(struct cfg* cfg) +{ + size_t i; + _gnutls_sign_mark_insecure_all(_INSECURE); + for (i = 0; cfg->sigs[i] != 0; i++) { + int ret = _gnutls_sign_set_secure(cfg->sigs[i], + _INSECURE_FOR_CERTS); + if (unlikely(ret < 0)) { + return gnutls_assert_val(ret); + } + } + for (i = 0; cfg->sigs_for_cert[i] != 0; i++) { + int ret = _gnutls_sign_set_secure(cfg->sigs_for_cert[i], + _SECURE); + if (unlikely(ret < 0)) { + return gnutls_assert_val(ret); + } + } + return 0; +} + +/* global side-effect! modifies `supported` in `sup_versions[]` */ +static inline int /* allowlisting-only */ +_cfg_versions_remark(struct cfg* cfg) +{ + size_t i; + _gnutls_version_mark_disabled_all(); + for (i = 0; cfg->versions[i] != 0; i++) { + int ret = _gnutls_protocol_set_enabled(cfg->versions[i], 1); + if (unlikely(ret < 0)) { + return gnutls_assert_val(ret); + } + } + return 0; +} + +/* global side-effect! modifies `supported` in `ecc_curves[]` */ +static inline int /* allowlisting-only */ +_cfg_ecc_curves_remark(struct cfg* cfg) +{ + size_t i; + _gnutls_ecc_curve_mark_disabled_all(); + for (i = 0; cfg->ecc_curves[i] != 0; i++) { + int ret = _gnutls_ecc_curve_set_enabled(cfg->ecc_curves[i], 1); + if (unlikely(ret < 0)) { + return gnutls_assert_val(ret); + } + } + return 0; +} + +/* + * setting arrays of struct cfg: from other arrays + */ + +static inline int /* allowlisting-only */ +cfg_hashes_set_array(struct cfg* cfg, + gnutls_digest_algorithm_t* src, size_t len) +{ + if (unlikely(len >= MAX_ALGOS)) { + return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR); + } + if (len) { + memcpy(cfg->hashes, + src, sizeof(gnutls_digest_algorithm_t) * len); + } + cfg->hashes[len] = 0; + return _cfg_hashes_remark(cfg); +} + +static inline int /* allowlisting-only */ +cfg_sigs_set_arrays(struct cfg* cfg, + gnutls_sign_algorithm_t* src, size_t len, + gnutls_sign_algorithm_t* src_for_cert, size_t len_for_cert) +{ + if (unlikely(len >= MAX_ALGOS)) { + return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR); + } + if (unlikely(len_for_cert >= MAX_ALGOS)) { + return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR); + } + if (len) { + memcpy(cfg->sigs, src, sizeof(gnutls_sign_algorithm_t) * len); + } + if (len_for_cert) { + memcpy(cfg->sigs_for_cert, src_for_cert, + sizeof(gnutls_sign_algorithm_t) * len_for_cert); + } + cfg->sigs[len] = 0; + cfg->sigs_for_cert[len_for_cert] = 0; + return _cfg_sigs_remark(cfg); +} + +static inline int /* allowlisting-only */ +cfg_versions_set_array(struct cfg* cfg, gnutls_protocol_t* src, size_t len) +{ + if (unlikely(len >= MAX_ALGOS)) { + return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR); + } + if (len) { + memcpy(cfg->versions, src, sizeof(gnutls_protocol_t) * len); + } + cfg->versions[len] = 0; + return _cfg_versions_remark(cfg); +} + +static inline int /* allowlisting-only */ +cfg_ecc_curves_set_array(struct cfg* cfg, gnutls_ecc_curve_t* src, size_t len) +{ + if (unlikely(len >= MAX_ALGOS)) { + return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR); + } + if (len) { + memcpy(cfg->ecc_curves, src, sizeof(gnutls_ecc_curve_t) * len); + } + cfg->ecc_curves[len] = 0; + return _cfg_ecc_curves_remark(cfg); +} + +/* + * appending to arrays of struct cfg + */ + +/* polymorphic way to DRY this operation. other possible approaches: + * 1. just unmacro (long) + * 2. cast to ints and write a function operating on ints + * (hacky, every call is +4 lines, needs a portable static assert) + * 3. macro whole functions, not just this operation (harder to find/read) + */ +#define APPEND_TO_NULL_TERMINATED_ARRAY(dst, element) \ + do { \ + size_t i; \ + for (i = 0; dst[i] != 0; i++) { \ + if (dst[i] == element) { \ + return 0; \ + } \ + } \ + if (unlikely(i >= MAX_ALGOS)) { \ + return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR); \ + } \ + dst[i] = element; \ + dst[i + 1] = 0; \ + } while (0) + +static inline int /* allowlisting-only */ +cfg_hashes_add(struct cfg *cfg, gnutls_digest_algorithm_t dig) +{ + _gnutls_debug_log("cfg: enabling digest algorithm %s\n", + gnutls_digest_get_name(dig)); + APPEND_TO_NULL_TERMINATED_ARRAY(cfg->hashes, dig); + return _cfg_hashes_remark(cfg); +} + +static inline int /* allowlisting-only */ +cfg_sigs_add(struct cfg *cfg, gnutls_sign_algorithm_t sig) +{ + _gnutls_debug_log("cfg: enabling signature algorithm " + "(for non-certificate usage) " + "%s\n", gnutls_sign_get_name(sig)); + APPEND_TO_NULL_TERMINATED_ARRAY(cfg->sigs, sig); + return _cfg_sigs_remark(cfg); +} + +static inline int /* allowlisting-only */ +cfg_sigs_for_cert_add(struct cfg *cfg, gnutls_sign_algorithm_t sig) +{ + _gnutls_debug_log("cfg: enabling signature algorithm" + "(for certificate usage) " + "%s\n", gnutls_sign_get_name(sig)); + APPEND_TO_NULL_TERMINATED_ARRAY(cfg->sigs_for_cert, sig); + return _cfg_sigs_remark(cfg); +} + +static inline int /* allowlisting-only */ +cfg_versions_add(struct cfg *cfg, gnutls_protocol_t prot) +{ + _gnutls_debug_log("cfg: enabling version %s\n", + gnutls_protocol_get_name(prot)); + APPEND_TO_NULL_TERMINATED_ARRAY(cfg->versions, prot); + return _cfg_versions_remark(cfg); +} + +static inline int /* allowlisting-only */ +cfg_ecc_curves_add(struct cfg *cfg, gnutls_ecc_curve_t curve) +{ + _gnutls_debug_log("cfg: enabling curve %s\n", + gnutls_ecc_curve_get_name(curve)); + APPEND_TO_NULL_TERMINATED_ARRAY(cfg->ecc_curves, curve); + return _cfg_ecc_curves_remark(cfg); +} + +#undef APPEND_TO_NULL_TERMINATED_ARRAY + +/* + * removing from arrays of struct cfg + */ + +/* polymorphic way to DRY this removal, see APPEND_TO_NULL_TERMINATED_ARRAY */ +#define REMOVE_FROM_NULL_TERMINATED_ARRAY(dst, element) \ + do { \ + size_t i, j; \ + for (i = 0; dst[i] != 0; i++) { \ + if (dst[i] == element) { \ + for (j = i; dst[j] != 0; j++) { \ + dst[j] = dst[j + 1]; \ + } \ + } \ + } \ + } while (0) + +static inline int /* allowlisting-only */ +cfg_hashes_remove(struct cfg *cfg, gnutls_digest_algorithm_t dig) +{ + _gnutls_debug_log("cfg: disabling digest algorithm %s\n", + gnutls_digest_get_name(dig)); + REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->hashes, dig); + return _cfg_hashes_remark(cfg); +} + +static inline int /* allowlisting-only */ +cfg_sigs_remove(struct cfg *cfg, gnutls_sign_algorithm_t sig) +{ + _gnutls_debug_log("cfg: disabling signature algorithm " + "(for non-certificate usage) " + "%s\n", gnutls_sign_get_name(sig)); + REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->sigs, sig); + return _cfg_sigs_remark(cfg); +} + +static inline int /* allowlisting-only */ +cfg_sigs_for_cert_remove(struct cfg *cfg, gnutls_sign_algorithm_t sig) +{ + _gnutls_debug_log("cfg: disabling signature algorithm" + "(for certificate usage) " + "%s\n", gnutls_sign_get_name(sig)); + REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->sigs_for_cert, sig); + return _cfg_sigs_remark(cfg); +} + +static inline int /* allowlisting-only */ +cfg_versions_remove(struct cfg *cfg, gnutls_protocol_t prot) +{ + _gnutls_debug_log("cfg: disabling version %s\n", + gnutls_protocol_get_name(prot)); + REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->versions, prot); + return _cfg_versions_remark(cfg); +} + +static inline int /* allowlisting-only */ +cfg_ecc_curves_remove(struct cfg *cfg, gnutls_ecc_curve_t curve) +{ + _gnutls_debug_log("cfg: disabling curve %s\n", + gnutls_ecc_curve_get_name(curve)); + REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->ecc_curves, curve); + return _cfg_ecc_curves_remark(cfg); } static inline int cfg_apply(struct cfg *cfg, struct ini_ctx *ctx) { size_t i; + int ret; cfg_steal(cfg, &ctx->cfg); @@ -1159,83 +1452,61 @@ cfg_apply(struct cfg *cfg, struct ini_ctx *ctx) } if (cfg->allowlisting) { - unsigned tls_sig_sem = 0; - size_t j; - - _gnutls_digest_mark_insecure_all(); - for (i = 0; i < ctx->hashes_size; i++) { - int ret = gnutls_digest_set_secure(ctx->hashes[i], 1); - if (unlikely(ret < 0)) { - return ret; - } - } - _gnutls_sign_mark_insecure_all(_INSECURE); - for (i = 0; i < ctx->sigs_size; i++) { - int ret = gnutls_sign_set_secure(ctx->sigs[i], 1); - if (unlikely(ret < 0)) { - return ret; - } - } - for (i = 0; i < ctx->sigs_for_cert_size; i++) { - int ret = gnutls_sign_set_secure_for_certs(ctx->sigs_for_cert[i], - 1); - if (unlikely(ret < 0)) { - return ret; - } + /* also updates `flags` of global `hash_algorithms[]` */ + ret = cfg_hashes_set_array(cfg, ctx->hashes, ctx->hashes_size); + if (unlikely(ret < 0)) { + return gnutls_assert_val(ret); } - _gnutls_version_mark_revertible_all(); - for (i = 0, j = 0; i < ctx->versions_size; i++) { - const version_entry_st *vers; - vers = version_to_entry(ctx->versions[i]); - if (vers && vers->supported) { - tls_sig_sem |= vers->tls_sig_sem; - cfg->versions[j++] = vers->id; - } + /* also updates `flags` of global `sign_algorithms[]` */ + ret = cfg_sigs_set_arrays(cfg, ctx->sigs, ctx->sigs_size, + ctx->sigs_for_cert, + ctx->sigs_for_cert_size); + if (unlikely(ret < 0)) { + return gnutls_assert_val(ret); } - _gnutls_ecc_curve_mark_disabled_all(); - for (i = 0; i < ctx->curves_size; i++) { - int ret = gnutls_ecc_curve_set_enabled(ctx->curves[i], 1); - if (unlikely(ret < 0)) { - return ret; - } + /* also updates `supported` field of global `sup_versions[]` */ + ret = cfg_versions_set_array(cfg, + ctx->versions, ctx->versions_size); + if (unlikely(ret < 0)) { + return gnutls_assert_val(ret); } - for (i = 0, j = 0; i < ctx->sigs_size; i++) { - const gnutls_sign_entry_st *se; - - se = _gnutls_sign_to_entry(ctx->sigs[i]); - if (se != NULL && se->aid.tls_sem & tls_sig_sem && - _gnutls_sign_is_secure2(se, 0)) { - cfg->sigs[j++] = se->id; - } + /* also updates `supported` field of global `ecc_curves[]` */ + ret = cfg_ecc_curves_set_array(cfg, + ctx->curves, ctx->curves_size); + if (unlikely(ret < 0)) { + return gnutls_assert_val(ret); } } else { + /* updates same global arrays as above, but doesn't store + * the algorithms into the `struct cfg` as allowlisting does. + * blocklisting doesn't allow relaxing the restrictions */ for (i = 0; i < ctx->hashes_size; i++) { - int ret = _gnutls_digest_mark_insecure(ctx->hashes[i]); + ret = _gnutls_digest_mark_insecure(ctx->hashes[i]); if (unlikely(ret < 0)) { return ret; } } for (i = 0; i < ctx->sigs_size; i++) { - int ret = _gnutls_sign_mark_insecure(ctx->sigs[i], + ret = _gnutls_sign_mark_insecure(ctx->sigs[i], _INSECURE); if (unlikely(ret < 0)) { return ret; } } for (i = 0; i < ctx->sigs_for_cert_size; i++) { - int ret = _gnutls_sign_mark_insecure(ctx->sigs_for_cert[i], _INSECURE_FOR_CERTS); + ret = _gnutls_sign_mark_insecure(ctx->sigs_for_cert[i], _INSECURE_FOR_CERTS); if (unlikely(ret < 0)) { return ret; } } for (i = 0; i < ctx->versions_size; i++) { - int ret = _gnutls_version_mark_disabled(ctx->versions[i]); + ret = _gnutls_version_mark_disabled(ctx->versions[i]); if (unlikely(ret < 0)) { return ret; } } for (i = 0; i < ctx->curves_size; i++) { - int ret = _gnutls_ecc_curve_mark_disabled(ctx->curves[i]); + ret = _gnutls_ecc_curve_mark_disabled(ctx->curves[i]); if (unlikely(ret < 0)) { return ret; } @@ -2311,7 +2582,9 @@ static int set_ciphersuite_list(gnutls_priority_t priority_cache) /* disable TLS versions which are added but are unsupported */ for (i = j = 0; i < priority_cache->protocol.num_priorities; i++) { vers = version_to_entry(priority_cache->protocol.priorities[i]); - if (!vers || vers->supported) + if (!vers || vers->supported || + (system_wide_config.allowlisting && \ + vers->supported_revertible)) priority_cache->protocol.priorities[j++] = priority_cache->protocol.priorities[i]; } priority_cache->protocol.num_priorities = j; @@ -3493,3 +3766,288 @@ gnutls_priority_string_list(unsigned iter, unsigned int flags) bool _gnutls_config_is_ktls_enabled(void){ return system_wide_config.ktls_enabled; } + +/* + * high-level interface for overriding configuration files + */ + +static inline bool /* not locking system_wide_config */ +system_wide_config_is_malleable(void) { + if (!system_wide_config.allowlisting) { + _gnutls_audit_log(NULL, "allowlisting is not enabled!\n"); + return false; + } + if (system_wide_config.priority_string) { + _gnutls_audit_log(NULL, "priority strings have already been " + "initialized!\n"); + return false; + } + return true; +} + +/** + * gnutls_digest_set_secure: + * @dig: is a digest algorithm + * @secure: whether to mark the digest algorithm secure + * + * Modify the previous system wide setting that marked @dig as secure + * or insecure. This only has effect when the algorithm is enabled + * through the allowlisting mode in the configuration file, or when + * the setting is modified with a prior call to this function. + * + * Since: 3.7.3 + */ +int +gnutls_digest_set_secure(gnutls_digest_algorithm_t dig, unsigned int secure) +{ +#ifndef DISABLE_SYSTEM_CONFIG + int ret; + ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock); + if (ret < 0) { + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return gnutls_assert_val(ret); + } + if (!system_wide_config_is_malleable()) { + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + } + + if (secure) { + ret = cfg_hashes_add(&system_wide_config, dig); + } else { + ret = cfg_hashes_remove(&system_wide_config, dig); + } + + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return ret; +#else + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); +#endif +} + +/** + * gnutls_sign_set_secure: + * @sign: the sign algorithm + * @secure: whether to mark the sign algorithm secure + * + * Modify the previous system wide setting that marked @sign as secure + * or insecure. Calling this function is allowed + * only if allowlisting mode is set in the configuration file, + * and only if the system-wide TLS priority string + * has not been initialized yet. + * The intended usage is to provide applications with a way + * to expressly deviate from the distribution or site defaults + * inherited from the configuration file. + * The modification is composable with further modifications + * performed through the priority string mechanism. + * + * This function is not thread-safe and is intended to be called + * in the main thread at the beginning of the process execution. + * + * Even when @secure is true, @sign is not marked as secure for the + * use in certificates. Use gnutls_sign_set_secure_for_certs() to + * mark it secure as well for certificates. + * + * Returns: 0 on success or negative error code otherwise. + * + * Since: 3.7.3 + */ +int +gnutls_sign_set_secure(gnutls_sign_algorithm_t sign, unsigned int secure) +{ +#ifndef DISABLE_SYSTEM_CONFIG + int ret; + ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock); + if (ret < 0) { + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return gnutls_assert_val(ret); + } + if (!system_wide_config_is_malleable()) { + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + } + + if (secure) { + ret = cfg_sigs_add(&system_wide_config, sign); + } else { + ret = cfg_sigs_remove(&system_wide_config, sign); + if (ret < 0) { + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return ret; + } + /* irregularity, distrusting also means distrusting for certs */ + ret = cfg_sigs_for_cert_remove(&system_wide_config, sign); + } + + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return ret; +#else + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); +#endif +} + + +/** + * gnutls_sign_set_secure_for_certs: + * @sign: the sign algorithm + * @secure: whether to mark the sign algorithm secure for certificates + * + * Modify the previous system wide setting that marked @sign as secure + * or insecure for the use in certificates. Calling this fuction is allowed + * only if allowlisting mode is set in the configuration file, + * and only if the system-wide TLS priority string + * has not been initialized yet. + * The intended usage is to provide applications with a way + * to expressly deviate from the distribution or site defaults + * inherited from the configuration file. + * The modification is composable with further modifications + * performed through the priority string mechanism. + * + * This function is not thread-safe and is intended to be called + * in the main thread at the beginning of the process execution. + + * When @secure is true, @sign is marked as secure for any use unlike + * gnutls_sign_set_secure(). Otherwise, it is marked as insecure only + * for the use in certificates. Use gnutls_sign_set_secure() to mark + * it insecure for any uses. + * + * Returns: 0 on success or negative error code otherwise. + * + * Since: 3.7.3 + */ +int +gnutls_sign_set_secure_for_certs(gnutls_sign_algorithm_t sign, + unsigned int secure) +{ +#ifndef DISABLE_SYSTEM_CONFIG + int ret; + ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock); + if (ret < 0) { + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return gnutls_assert_val(ret); + } + if (!system_wide_config_is_malleable()) { + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + } + + if (secure) { + /* irregularity, trusting for certs means trusting in general */ + ret = cfg_sigs_add(&system_wide_config, sign); + if (ret < 0) { + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return ret; + } + ret = cfg_sigs_for_cert_add(&system_wide_config, sign); + } else { + ret = cfg_sigs_for_cert_remove(&system_wide_config, sign); + } + + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return ret; +#else + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); +#endif +} + +/** + * gnutls_protocol_set_enabled: + * @version: is a (gnutls) version number + * @enabled: whether to enable the protocol + * + * Control the previous system-wide setting that marked @version as + * enabled or disabled. Calling this fuction is allowed + * only if allowlisting mode is set in the configuration file, + * and only if the system-wide TLS priority string + * has not been initialized yet. + * The intended usage is to provide applications with a way + * to expressly deviate from the distribution or site defaults + * inherited from the configuration file. + * The modification is composable with further modifications + * performed through the priority string mechanism. + * + * This function is not thread-safe and is intended to be called + * in the main thread at the beginning of the process execution. + * + * Returns: 0 on success or negative error code otherwise. + * + * Since: 3.7.3 + */ +int /* allowlisting-only */ /* not thread-safe */ +gnutls_protocol_set_enabled(gnutls_protocol_t version, unsigned int enabled) +{ +#ifndef DISABLE_SYSTEM_CONFIG + int ret; + ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock); + if (ret < 0) { + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return gnutls_assert_val(ret); + } + if (!system_wide_config_is_malleable()) { + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + } + + if (enabled) { + ret = cfg_versions_add(&system_wide_config, version); + } else { + ret = cfg_versions_remove(&system_wide_config, version); + } + + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return ret; +#else + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); +#endif +} + +/** + * gnutls_ecc_curve_set_enabled: + * @curve: is an ECC curve + * @enabled: whether to enable the curve + * + * Modify the previous system wide setting that marked @curve as + * enabled or disabled. Calling this fuction is allowed + * only if allowlisting mode is set in the configuration file, + * and only if the system-wide TLS priority string + * has not been initialized yet. + * The intended usage is to provide applications with a way + * to expressly deviate from the distribution or site defaults + * inherited from the configuration file. + * The modification is composable with further modifications + * performed through the priority string mechanism. + * + * This function is not thread-safe and is intended to be called + * in the main thread at the beginning of the process execution. + * + * Returns: 0 on success or negative error code otherwise. + * + * Since: 3.7.3 + */ +int +gnutls_ecc_curve_set_enabled(gnutls_ecc_curve_t curve, unsigned int enabled) +{ +#ifndef DISABLE_SYSTEM_CONFIG + int ret; + ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock); + if (ret < 0) { + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return gnutls_assert_val(ret); + } + if (!system_wide_config_is_malleable()) { + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + } + + if (enabled) { + ret = cfg_ecc_curves_add(&system_wide_config, curve); + } else { + ret = cfg_ecc_curves_remove(&system_wide_config, curve); + } + + (void)gnutls_rwlock_unlock(&system_wide_config_rwlock); + return ret; +#else + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); +#endif +} diff --git a/lib/state.c b/lib/state.c index ee72646128..9e16d99300 100644 --- a/lib/state.c +++ b/lib/state.c @@ -1369,7 +1369,7 @@ gnutls_session_channel_binding(gnutls_session_t session, if (cbtype == GNUTLS_CB_TLS_UNIQUE) { const version_entry_st *ver = get_version(session); if (unlikely(ver == NULL || ver->tls13_sem)) - return GNUTLS_E_INVALID_REQUEST; + return GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE; cb->size = session->internals.cb_tls_unique_len; cb->data = gnutls_malloc(cb->size); @@ -1461,6 +1461,21 @@ gnutls_session_channel_binding(gnutls_session_t session, #define EXPORTER_CTX_DATA "" #define EXPORTER_CTX_LEN 0 + const version_entry_st *ver = get_version(session); + if (unlikely(ver == NULL)) { + return GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE; + } + + /* "tls-exporter" channel binding is defined only when + * the TLS handshake results in unique master secrets, + * i.e., either TLS 1.3, or TLS 1.2 with extended + * master secret negotiated. + */ + if (!ver->tls13_sem && + gnutls_session_ext_master_secret_status(session) == 0) { + return GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE; + } + cb->size = 32; cb->data = gnutls_malloc(cb->size); if (cb->data == NULL) diff --git a/lib/system/keys-win.c b/lib/system/keys-win.c index 4463c3b2d7..a0fffe249e 100644 --- a/lib/system/keys-win.c +++ b/lib/system/keys-win.c @@ -254,7 +254,7 @@ int capi_sign(gnutls_privkey_t key, void *userdata, { priv_st *priv = (priv_st *) userdata; ALG_ID Algid; - HCRYPTHASH hHash = NULL; + HCRYPTHASH hHash = 0; uint8_t digest[MAX_HASH_SIZE]; unsigned int digest_size; gnutls_digest_algorithm_t algo; @@ -441,7 +441,7 @@ static int privkey_import_capi(gnutls_privkey_t pkey, const char *url, priv_st *priv, CRYPT_KEY_PROV_INFO *kpi) { - HCRYPTPROV hCryptProv = NULL; + HCRYPTPROV hCryptProv = 0; int ret, enc_too = 0; DWORD i, dwErrCode = 0; @@ -702,7 +702,7 @@ int privkey_import_ncrypt(gnutls_privkey_t pkey, const char *url, priv_st *priv, CRYPT_KEY_PROV_INFO *kpi, NCRYPT_PROV_HANDLE *sctx) { SECURITY_STATUS r; - NCRYPT_KEY_HANDLE nc = NULL; + NCRYPT_KEY_HANDLE nc = 0; int ret, enc_too = 0; WCHAR algo_str[64]; DWORD algo_str_size = 0; @@ -786,7 +786,7 @@ int _gnutls_privkey_import_system_url(gnutls_privkey_t pkey, const char *url) const CERT_CONTEXT *cert = NULL; CRYPT_HASH_BLOB blob; CRYPT_KEY_PROV_INFO *kpi = NULL; - NCRYPT_PROV_HANDLE sctx = NULL; + NCRYPT_PROV_HANDLE sctx = 0; DWORD kpi_size; SECURITY_STATUS r; int ret; diff --git a/lib/tls13/certificate_request.c b/lib/tls13/certificate_request.c index 37e7b41049..b613cab13f 100644 --- a/lib/tls13/certificate_request.c +++ b/lib/tls13/certificate_request.c @@ -25,6 +25,7 @@ #include "extv.h" #include "handshake.h" #include "tls13/certificate_request.h" +#include "ext/compress_certificate.h" #include "ext/signature.h" #include "ext/status_request.h" #include "mbuffers.h" @@ -128,6 +129,13 @@ int parse_cert_extension(void *_ctx, unsigned tls_id, const uint8_t *data, unsig ctx->rdn = data+2; ctx->rdn_size = v; + } else if (tls_id == ext_mod_compress_certificate.tls_id) { + ret = _gnutls_compress_certificate_recv_params(session, + data, + data_size); + if (ret < 0) { + return gnutls_assert_val(ret); + } } return 0; @@ -357,6 +365,13 @@ int _gnutls13_send_certificate_request(gnutls_session_t session, unsigned again) session->internals.hsk_flags |= HSK_CLIENT_OCSP_REQUESTED; #endif + ret = _gnutls_extv_append(&buf, ext_mod_compress_certificate.tls_id, session, + (extv_append_func)_gnutls_compress_certificate_send_params); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + ret = _gnutls_extv_append_final(&buf, init_pos, 0); if (ret < 0) { gnutls_assert(); diff --git a/lib/x509/privkey_pkcs8_pbes1.c b/lib/x509/privkey_pkcs8_pbes1.c index c296807974..983530e46a 100644 --- a/lib/x509/privkey_pkcs8_pbes1.c +++ b/lib/x509/privkey_pkcs8_pbes1.c @@ -140,7 +140,7 @@ _gnutls_decrypt_pbes1_des_md5_data(const char *password, { int result; gnutls_datum_t dkey, d_iv; - cipher_hd_st ch; + gnutls_cipher_hd_t ch; uint8_t key[16]; const unsigned block_size = 8; @@ -158,16 +158,14 @@ _gnutls_decrypt_pbes1_des_md5_data(const char *password, dkey.size = 8; d_iv.data = &key[8]; d_iv.size = 8; - result = - _gnutls_cipher_init(&ch, cipher_to_entry(GNUTLS_CIPHER_DES_CBC), - &dkey, &d_iv, 0); + result = gnutls_cipher_init(&ch, GNUTLS_CIPHER_DES_CBC, &dkey, &d_iv); if (result < 0) { _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR); return gnutls_assert_val(result); } _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED); - result = _gnutls_cipher_decrypt(&ch, encrypted_data->data, encrypted_data->size); + result = gnutls_cipher_decrypt(ch, encrypted_data->data, encrypted_data->size); if (result < 0) { gnutls_assert(); goto error; @@ -184,7 +182,7 @@ _gnutls_decrypt_pbes1_des_md5_data(const char *password, result = 0; error: - _gnutls_cipher_deinit(&ch); + gnutls_cipher_deinit(ch); return result; } diff --git a/m4/hooks.m4 b/m4/hooks.m4 index c32b3bc380..f3cdaa8586 100644 --- a/m4/hooks.m4 +++ b/m4/hooks.m4 @@ -41,7 +41,7 @@ AC_DEFUN([LIBGNUTLS_HOOKS], # # Interfaces removed: AGE=0 (+bump all symbol versions in .map) AC_SUBST(LT_CURRENT, 64) - AC_SUBST(LT_REVISION, 1) + AC_SUBST(LT_REVISION, 2) AC_SUBST(LT_AGE, 34) AC_SUBST(LT_SSL_CURRENT, 27) diff --git a/src/cli.c b/src/cli.c index fb7f957b48..7c031f1ec3 100644 --- a/src/cli.c +++ b/src/cli.c @@ -1654,6 +1654,7 @@ static void cmd_parser(int argc, char **argv) for (p = gnutls_get_library_config(); p->name; p++) { log_msg(stdout, "%s: %s\n", p->name, p->value); } + log_msg(stdout, "system-config: %s\n", gnutls_get_system_config_file()); exit(0); } diff --git a/src/common.c b/src/common.c index 827157424b..6d2056f95e 100644 --- a/src/common.c +++ b/src/common.c @@ -442,6 +442,51 @@ static void print_ecdh_info(gnutls_session_t session, const char *str, int print } +struct channel_binding_request { + gnutls_channel_binding_t type; + const char *name; +}; + +static void print_channel_bindings(gnutls_session_t session, int print) +{ + static const struct channel_binding_request requests[] = { + { GNUTLS_CB_TLS_UNIQUE, "tls-unique" }, + { GNUTLS_CB_TLS_SERVER_END_POINT, "tls-server-end-point" }, + { GNUTLS_CB_TLS_EXPORTER, "tls-exporter" } + }; + size_t i; + + if (!print) { + return; + } + + log_msg(stdout, "- Channel bindings\n"); + for (i = 0; i < sizeof(requests) / sizeof(requests[0]); i++) { + gnutls_datum_t cb; + int rc; + + rc = gnutls_session_channel_binding(session, + requests[i].type, + &cb); + if (rc == GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE) { + log_msg(stdout, " - '%s': not available\n", + requests[i].name); + } else if (rc < 0) { + fprintf(stderr, " - '%s': error: %s\n", + requests[i].name, gnutls_strerror(rc)); + } else { + size_t j; + + log_msg(stdout, " - '%s': ", + requests[i].name); + for (j = 0; j < cb.size; j++) + log_msg(stdout, "%02x", cb.data[j]); + log_msg(stdout, "\n"); + gnutls_free(cb.data); + } + } +} + int print_info(gnutls_session_t session, int verbose, int flags) { const char *tmp; @@ -599,25 +644,7 @@ int print_info(gnutls_session_t session, int verbose, int flags) log_msg(stdout, "- Application protocol: %.*s\n", p.size, p.data); #endif - if (verbose) { - gnutls_datum_t cb; - - rc = gnutls_session_channel_binding(session, - GNUTLS_CB_TLS_EXPORTER, - &cb); - if (rc) - fprintf(stderr, "Channel binding error: %s\n", - gnutls_strerror(rc)); - else { - size_t i; - - log_msg(stdout, "- Channel binding 'tls-exporter': "); - for (i = 0; i < cb.size; i++) - log_msg(stdout, "%02x", cb.data[i]); - log_msg(stdout, "\n"); - gnutls_free(cb.data); - } - } + print_channel_bindings(session, verbose); fflush(stdout); diff --git a/src/srptool-options.json b/src/srptool-options.json index f24dea9f74..b221f01bae 100644 --- a/src/srptool-options.json +++ b/src/srptool-options.json @@ -25,7 +25,8 @@ "long-option": "index", "short-option": "i", "description": "specify the index of the group parameters in tpasswd.conf to use", - "argument-type": "number" + "argument-type": "number", + "argument-default": 3 }, { "long-option": "username", @@ -66,4 +67,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/tests/Makefile.am b/tests/Makefile.am index d261a3ddee..3e126f0046 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -122,7 +122,7 @@ ctests = tls13/supported_versions tls13/tls12-no-tls13-exts \ tls12-check-rollback-val tls11-check-rollback-val \ tls13/post-handshake-with-psk tls13/post-handshake-with-cert-auto \ tls13/anti_replay tls13/compress-cert tls13/compress-cert-neg \ - tls13/compress-cert-neg2 + tls13/compress-cert-neg2 tls13/compress-cert-cli ctests += tls13/hello_retry_request @@ -233,7 +233,8 @@ ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniquei tls13-without-timeout-func buffer status-request-revoked \ set_x509_ocsp_multi_cli kdf-api keylog-func handshake-write \ x509cert-dntypes id-on-xmppAddr tls13-compat-mode ciphersuite-name \ - x509-upnconstraint cipher-padding pkcs7-verify-double-free + x509-upnconstraint cipher-padding pkcs7-verify-double-free \ + fips-rsa-sizes ctests += tls-channel-binding diff --git a/tests/fips-rsa-sizes.c b/tests/fips-rsa-sizes.c new file mode 100644 index 0000000000..84b9affabb --- /dev/null +++ b/tests/fips-rsa-sizes.c @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2022 Red Hat, Inc. + * + * Author: Alexander Sosedkin + * + * This file is part of GnuTLS. + * + * GnuTLS is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuTLS 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 a copy of the GNU General Public License + * along with GnuTLS; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include + +#define FIPS_PUSH_CONTEXT() do { \ + ret = gnutls_fips140_push_context(fips_context); \ + if (ret < 0) { \ + fail("gnutls_fips140_push_context failed\n"); \ + } \ +} while (0) + +#define FIPS_POP_CONTEXT(state) do { \ + ret = gnutls_fips140_pop_context(); \ + if (ret < 0) { \ + fail("gnutls_fips140_context_pop failed\n"); \ + } \ + fips_state = gnutls_fips140_get_operation_state(fips_context); \ + if (fips_state != GNUTLS_FIPS140_OP_ ## state) { \ + fail("operation state is not " # state " (%d)\n", \ + fips_state); \ + } \ +} while (0) + + +void generate_successfully(gnutls_privkey_t* privkey, gnutls_pubkey_t* pubkey, + unsigned int size); +void generate_unsuccessfully(gnutls_privkey_t* privkey, gnutls_pubkey_t* pubkey, + unsigned int size); +void sign_verify_successfully(gnutls_privkey_t privkey, gnutls_pubkey_t pubkey); +void sign_verify_unsuccessfully(gnutls_privkey_t privkey, + gnutls_pubkey_t pubkey); +void nosign_verify(gnutls_privkey_t privkey, gnutls_pubkey_t pubkey); + + +void generate_successfully(gnutls_privkey_t* privkey, gnutls_pubkey_t* pubkey, + unsigned int size) +{ + int ret; + gnutls_x509_privkey_t xprivkey; + gnutls_fips140_context_t fips_context; + gnutls_fips140_operation_state_t fips_state; + assert(gnutls_fips140_context_init(&fips_context) == 0); + + fprintf(stderr, "%d-bit\n", size); + + /* x509 generation as well just because why not */ + FIPS_PUSH_CONTEXT(); + assert(gnutls_x509_privkey_init(&xprivkey) == 0); + ret = gnutls_x509_privkey_generate(xprivkey, GNUTLS_PK_RSA, size, 0); + if (ret != GNUTLS_E_SUCCESS) + fail("%d-bit x509_privkey_init (%d)\n", size, ret); + FIPS_POP_CONTEXT(APPROVED); + gnutls_x509_privkey_deinit(xprivkey); + + FIPS_PUSH_CONTEXT(); + assert(gnutls_privkey_init(privkey) == 0); + ret = gnutls_privkey_generate(*privkey, GNUTLS_PK_RSA, size, 0); + if (ret != GNUTLS_E_SUCCESS) + fail("%d-bit privkey_init (%d)\n", size, ret); + FIPS_POP_CONTEXT(APPROVED); + + assert(gnutls_pubkey_init(pubkey) == 0); + FIPS_PUSH_CONTEXT(); + ret = gnutls_pubkey_import_privkey(*pubkey, *privkey, + GNUTLS_KEY_DIGITAL_SIGNATURE, 0); + if (ret != GNUTLS_E_SUCCESS) + fail("%d-bit pubkey_import_privkey (%d)\n", size, ret); + FIPS_POP_CONTEXT(INITIAL); + + gnutls_fips140_context_deinit(fips_context); +} + + +void generate_unsuccessfully(gnutls_privkey_t* privkey, gnutls_pubkey_t* pubkey, + unsigned int size) +{ + int ret; + gnutls_x509_privkey_t xprivkey; + gnutls_fips140_context_t fips_context; + gnutls_fips140_operation_state_t fips_state; + assert(gnutls_fips140_context_init(&fips_context) == 0); + + fprintf(stderr, "%d-bit\n", size); + + /* short x509 generation: ERROR, blocked */ + FIPS_PUSH_CONTEXT(); + assert(gnutls_x509_privkey_init(&xprivkey) == 0); + ret = gnutls_x509_privkey_generate(xprivkey, GNUTLS_PK_RSA, size, 0); + if (ret != GNUTLS_E_PK_GENERATION_ERROR) + fail("%d-bit x509_privkey_init (%d)\n", size, ret); + FIPS_POP_CONTEXT(ERROR); + gnutls_x509_privkey_deinit(xprivkey); + + /* short key generation: ERROR, blocked */ + FIPS_PUSH_CONTEXT(); + assert(gnutls_privkey_init(privkey) == 0); + ret = gnutls_privkey_generate(*privkey, GNUTLS_PK_RSA, size, 0); + if (ret != GNUTLS_E_PK_GENERATION_ERROR) + fail("%d-bit privkey_init (%d)\n", size, ret); + FIPS_POP_CONTEXT(ERROR); + gnutls_privkey_deinit(*privkey); + + /* Disable FIPS to generate them anyway */ + gnutls_fips140_set_mode(GNUTLS_FIPS140_LAX, 0); + assert(gnutls_fips140_mode_enabled() == GNUTLS_FIPS140_LAX); + + assert(gnutls_x509_privkey_init(&xprivkey) == 0); + ret = gnutls_x509_privkey_generate(xprivkey, GNUTLS_PK_RSA, size, 0); + if (ret != GNUTLS_E_SUCCESS) + fail("%d-bit x509_privkey_init (%d)\n", size, ret); + gnutls_x509_privkey_deinit(xprivkey); + + assert(gnutls_privkey_init(privkey) == 0); + ret = gnutls_privkey_generate(*privkey, GNUTLS_PK_RSA, size, 0); + if (ret != GNUTLS_E_SUCCESS) + fail("%d-bit privkey_init (%d)\n", size, ret); + + assert(gnutls_pubkey_init(pubkey) == 0); + ret = gnutls_pubkey_import_privkey(*pubkey, *privkey, + GNUTLS_KEY_DIGITAL_SIGNATURE, 0); + if (ret != GNUTLS_E_SUCCESS) + fail("%d-bit pubkey_import_privkey (%d)\n", size, ret); + + gnutls_fips140_set_mode(GNUTLS_FIPS140_STRICT, 0); + assert(gnutls_fips140_mode_enabled()); + + gnutls_fips140_context_deinit(fips_context); +} + + +void sign_verify_successfully(gnutls_privkey_t privkey, gnutls_pubkey_t pubkey) { + int ret; + gnutls_fips140_context_t fips_context; + gnutls_fips140_operation_state_t fips_state; + + gnutls_datum_t signature; + gnutls_datum_t plaintext = { + .data = (unsigned char* const) "Hello world!", + .size = 12 + }; + assert(gnutls_fips140_context_init(&fips_context) == 0); + + /* RSA sign: approved */ + FIPS_PUSH_CONTEXT(); + ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0, + &plaintext, &signature); + if (ret < 0) + fail("gnutls_privkey_sign_data failed\n"); + FIPS_POP_CONTEXT(APPROVED); + + /* RSA verify: approved */ + FIPS_PUSH_CONTEXT(); + ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA256, 0, + &plaintext, &signature); + if (ret < 0) + fail("gnutls_pubkey_verify_data2 failed\n"); + FIPS_POP_CONTEXT(APPROVED); + + gnutls_free(signature.data); + gnutls_fips140_context_deinit(fips_context); +} + + +void sign_verify_unsuccessfully(gnutls_privkey_t privkey, + gnutls_pubkey_t pubkey) { + int ret; + gnutls_fips140_context_t fips_context; + gnutls_fips140_operation_state_t fips_state; + + gnutls_datum_t signature; + gnutls_datum_t plaintext = { + .data = (unsigned char* const) "Hello world!", + .size = 12 + }; + assert(gnutls_fips140_context_init(&fips_context) == 0); + + /* small key RSA sign: not approved */ + FIPS_PUSH_CONTEXT(); + ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0, + &plaintext, &signature); + if (ret < 0) + fail("gnutls_privkey_sign_data failed\n"); + FIPS_POP_CONTEXT(NOT_APPROVED); + + /* small key RSA verify: not approved */ + FIPS_PUSH_CONTEXT(); + ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA256, 0, + &plaintext, &signature); + if (ret < 0) + fail("gnutls_pubkey_verify_data2 failed\n"); + FIPS_POP_CONTEXT(NOT_APPROVED); + + gnutls_free(signature.data); + gnutls_pubkey_deinit(pubkey); + gnutls_privkey_deinit(privkey); + gnutls_fips140_context_deinit(fips_context); +} + + +void nosign_verify(gnutls_privkey_t privkey, gnutls_pubkey_t pubkey) { + int ret; + gnutls_fips140_context_t fips_context; + gnutls_fips140_operation_state_t fips_state; + + gnutls_datum_t signature; + gnutls_datum_t plaintext = { + .data = (unsigned char* const) "Hello world!", + .size = 12 + }; + assert(gnutls_fips140_context_init(&fips_context) == 0); + + /* 1024, 1280, 1536, 1792 key RSA sign: not approved */ + FIPS_PUSH_CONTEXT(); + ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0, + &plaintext, &signature); + if (ret < 0) + fail("gnutls_privkey_sign_data failed\n"); + FIPS_POP_CONTEXT(NOT_APPROVED); + + /* Disable FIPS to sign them anyway */ + gnutls_fips140_set_mode(GNUTLS_FIPS140_LAX, 0); + assert(gnutls_fips140_mode_enabled() == GNUTLS_FIPS140_LAX); + + ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0, + &plaintext, &signature); + if (ret < 0) + fail("gnutls_privkey_sign_data failed\n"); + + gnutls_fips140_set_mode(GNUTLS_FIPS140_STRICT, 0); + assert(gnutls_fips140_mode_enabled()); + + /* 1024, 1280, 1536, 1792 key RSA verify: approved (exception) */ + FIPS_PUSH_CONTEXT(); + ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA256, 0, + &plaintext, &signature); + if (ret < 0) + fail("gnutls_pubkey_verify_data2 failed\n"); + FIPS_POP_CONTEXT(APPROVED); + + gnutls_free(signature.data); + gnutls_pubkey_deinit(pubkey); + gnutls_privkey_deinit(privkey); + gnutls_fips140_context_deinit(fips_context); +} + + +void doit(void) +{ + gnutls_fips140_context_t fips_context; + gnutls_privkey_t privkey; + gnutls_pubkey_t pubkey; + + if (gnutls_fips140_mode_enabled() == 0) { + success("We are not in FIPS140 mode\n"); + exit(77); /* SKIP */ + } + + assert(gnutls_fips140_context_init(&fips_context) == 0); + + /* 512-bit RSA: no generate, no sign, no verify */ + generate_unsuccessfully(&privkey, &pubkey, 512); + sign_verify_unsuccessfully(privkey, pubkey); + /* 512-bit RSA again (to be safer about going in and out of FIPS) */ + generate_unsuccessfully(&privkey, &pubkey, 512); + sign_verify_unsuccessfully(privkey, pubkey); + /* 600-bit RSA: no generate, no sign, no verify */ + generate_unsuccessfully(&privkey, &pubkey, 600); + sign_verify_unsuccessfully(privkey, pubkey); + + /* 768-bit RSA not-an-exception: nogenerate, nosign, verify */ + generate_unsuccessfully(&privkey, &pubkey, 768); + sign_verify_unsuccessfully(privkey, pubkey); + /* 1024-bit RSA exception: nogenerate, nosign, verify */ + generate_unsuccessfully(&privkey, &pubkey, 1024); + nosign_verify(privkey, pubkey); + /* 1280-bit RSA exception: nogenerate, nosign, verify */ + generate_unsuccessfully(&privkey, &pubkey, 1280); + nosign_verify(privkey, pubkey); + /* 1500-bit RSA not-an-exception: nogenerate, nosign, noverify */ + generate_unsuccessfully(&privkey, &pubkey, 1500); + sign_verify_unsuccessfully(privkey, pubkey); + /* 1536-bit RSA exception: nogenerate, nosign, verify */ + generate_unsuccessfully(&privkey, &pubkey, 1536); + nosign_verify(privkey, pubkey); + /* 1792-bit RSA exception: nogenerate, nosign, verify */ + generate_unsuccessfully(&privkey, &pubkey, 1792); + nosign_verify(privkey, pubkey); + /* 2000-bit RSA not-an-exception: nogenerate, nosign, noverify */ + generate_unsuccessfully(&privkey, &pubkey, 2000); + sign_verify_unsuccessfully(privkey, pubkey); + + /* 2048-bit RSA: generate, sign, verify */ + generate_successfully(&privkey, &pubkey, 2048); + sign_verify_successfully(privkey, pubkey); + /* 2432-bit RSA: nogenerate, sign, verify */ + generate_unsuccessfully(&privkey, &pubkey, 2432); + sign_verify_successfully(privkey, pubkey); + /* 3072-bit RSA: generate, sign, verify */ + generate_successfully(&privkey, &pubkey, 3072); + sign_verify_successfully(privkey, pubkey); + + gnutls_fips140_context_deinit(fips_context); +} diff --git a/tests/ktls.sh b/tests/ktls.sh index ba52bd5775..cace3286dc 100755 --- a/tests/ktls.sh +++ b/tests/ktls.sh @@ -24,7 +24,7 @@ . "$srcdir/scripts/common.sh" -if ! grep '^tls ' /proc/modules 2>1 >& /dev/null; then +if ! grep '^tls ' /proc/modules 2>&1 /dev/null; then exit 77 fi diff --git a/tests/protocol-set-allowlist.c b/tests/protocol-set-allowlist.c index 754e4d12d1..744d70b315 100644 --- a/tests/protocol-set-allowlist.c +++ b/tests/protocol-set-allowlist.c @@ -37,15 +37,21 @@ * This is not a test by itself. * This is a helper for the real test in protocol-set-allowlist.sh. * It executes sequences of commands like: - * > connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) - * > protocol_set_disabled TLS1.2 -> OK - * > connect -> bad priority: (actually, any arrow-less text can go here) + * > protocol_set_disabled TLS1.2 + * > protocol_set_enabled TLS1.1 + * > connect + * > protocol_set_enabled TLS1.2 + * > protocol_set_disabled TLS1.1 + * > connect -> connection established * where `connect` connects to $TEST_SERVER_PORT using $TEST_SERVER_CA, * and gnutls_protocol_set_enabled simply call the underlying API. * leaving the outer test to check return code and output: - * connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) * protocol_set_disabled TLS1.2 -> OK - * connect -> bad priority: No or insufficient priorities were set. + * protocol_set_enabled TLS1.1 -> OK + * connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) + * protocol_set_enabled TLS1.2 -> INVALID_REQUEST + * protocol_set_disabled TLS1.1 -> INVALID_REQUEST + * connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) */ #define _assert(cond, format, ...) if (!(cond)) \ @@ -58,6 +64,7 @@ void test_echo_server(gnutls_session_t session); void cmd_connect(const char* ca_file, unsigned port); void cmd_protocol_set_disabled(const char* name); void cmd_protocol_set_enabled(const char* name); +void cmd_reinit(void); const char* unprefix(const char* s, const char* prefix); @@ -167,15 +174,32 @@ void cmd_connect(const char* ca_file, unsigned port) void cmd_protocol_set_disabled(const char* name) { - _check(gnutls_protocol_set_enabled(parse_protocol(name), 0) >= 0); - printf("protocol_set_disabled %s -> OK\n", name); + int ret; + ret = gnutls_protocol_set_enabled(parse_protocol(name), 0); + printf("protocol_set_disabled %s -> %s\n", name, + ret == 0 ? "OK" : + ret == GNUTLS_E_INVALID_REQUEST ? "INVALID_REQUEST" : + gnutls_strerror(ret)); } void cmd_protocol_set_enabled(const char* name) { - _check(gnutls_protocol_set_enabled(parse_protocol(name), 1) >= 0); - printf("protocol_set_enabled %s -> OK\n", name); + int ret; + ret = gnutls_protocol_set_enabled(parse_protocol(name), 1); + printf("protocol_set_enabled %s -> %s\n", name, + ret == 0 ? "OK" : + ret == GNUTLS_E_INVALID_REQUEST ? "INVALID_REQUEST" : + gnutls_strerror(ret)); +} + + +void cmd_reinit(void) +{ + int ret; + gnutls_global_deinit(); + ret = gnutls_global_init(); + printf("reinit -> %s\n", ret == 0 ? "OK" : gnutls_strerror(ret)); } @@ -204,8 +228,6 @@ void doit(void) _assert(port_str, "TEST_SERVER_PORT is not set"); port = parse_port(port_str); - _check(gnutls_global_init() >= 0); - while (!feof(stdin)) { memset(cmd_buf, '\0', MAX_CMD_LEN + 1); fgets(cmd_buf, MAX_CMD_LEN, stdin); @@ -220,6 +242,8 @@ void doit(void) cmd_protocol_set_disabled(p); else if ((p = unprefix(cmd_buf, "> protocol_set_enabled "))) cmd_protocol_set_enabled(p); + else if (!strcmp(cmd_buf, "> reinit")) + cmd_reinit(); else if ((p = unprefix(cmd_buf, "> "))) _fail("Unknown command `%s`\n", p); else @@ -227,6 +251,5 @@ void doit(void) cmd_buf); } - gnutls_global_deinit(); exit(0); } diff --git a/tests/protocol-set-allowlist.sh b/tests/protocol-set-allowlist.sh index 907f37562f..ee2fe649bd 100755 --- a/tests/protocol-set-allowlist.sh +++ b/tests/protocol-set-allowlist.sh @@ -25,6 +25,7 @@ # from within the shell wrapper protocol-set-allowlist.sh # The shell part of it feeds commands into a C helper # and compares its output to the reference output. +# Commands are derived from the reference output. : ${srcdir=.} : ${builddir=.} @@ -161,6 +162,9 @@ fi ### Harness for the actual tests test_with_helper() { + echo '#' + echo "# $1" + echo '#' ${CAT} > "$TMPFILE_EXPECTED_LOG" ${SED} 's/\(.*\) -> .*/> \1/' "${TMPFILE_EXPECTED_LOG}" \ > "${TMPFILE_INPUT_SCRIPT}" @@ -197,152 +201,234 @@ launch_server --echo --priority "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.2" \ SERVER_PID=$! wait_server ${SERVER_PID} -# ["gnutls_protocol_set_enabled can disable, TLS"] -# With a configuration file allowlisting a specific TLS protocol version (1.2), -# gnutls_protocol_set_enabled can disable it. -test_with_helper < connection established: (TLS1.2)-(RSA)-(AES-128-GCM) -protocol_set_disabled TLS1.2 -> OK -connect -> bad priority: No or insufficient priorities were set. EOF -# ["gnutls_protocol_set_enabled disables revertibly, TLS"] -# consecutive gnutls_protocol_set_enabled can make connection possible -# (with a different session handle). -test_with_helper < connection established: (TLS1.2)-(RSA)-(AES-128-GCM) -protocol_set_disabled TLS1.2 -> OK -connect -> bad priority: No or insufficient priorities were set. -protocol_set_enabled TLS1.2 -> OK +protocol_set_disabled TLS1.2 -> INVALID_REQUEST connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) EOF -# Just a random long-ish scenario -test_with_helper < connection established: (TLS1.2)-(RSA)-(AES-128-GCM) +test_with_helper 'disabling TLS 1.2 leaves us with no versions' < OK connect -> bad priority: No or insufficient priorities were set. -protocol_set_enabled TLS1.3 -> OK +protocol_set_enabled TLS1.2 -> INVALID_REQUEST connect -> bad priority: No or insufficient priorities were set. -protocol_set_disabled TLS1.3 -> OK +EOF + +test_with_helper \ + 'disabling is revertible if done before the first gnutls_init' << EOF +protocol_set_disabled TLS1.2 -> OK protocol_set_enabled TLS1.2 -> OK connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) +protocol_set_disabled TLS1.2 -> INVALID_REQUEST +protocol_set_enabled TLS1.2 -> INVALID_REQUEST +connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) EOF -# !!! CURRENTLY NOT WORKING AS EXPECTED !!! -# Insufficient priority vs handshake failed -#test_with_helper < OK +#connect -> bad priority: No or insufficient priorities were set. +#reinit -> OK +#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) +#EOF + +# Reinit after restricting algorithms has problems with FIPS self-tests +#test_with_helper \ +# 'library reinitialization allows new API again, but resets changes' \ +# < OK #connect -> bad priority: No or insufficient priorities were set. -#protocol_set_enabled TLS1.3 -> OK -#connect -> handshake failed: A packet with illegal or unsupported version was received. +#protocol_set_enabled TLS1.2 -> INVALID_REQUEST +#connect -> bad priority: No or insufficient priorities were set. +#reinit -> OK +#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) +#protocol_set_disabled TLS1.2 -> INVALID_REQUEST +#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) +#reinit -> OK +#protocol_set_disabled TLS1.2 -> OK +#protocol_set_enabled TLS1.2 -> OK +#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) +#protocol_set_disabled TLS1.2 -> INVALID_REQUEST #EOF +test_with_helper 'Insufficient priority vs handshake failed: 1/2' < OK +connect -> bad priority: No or insufficient priorities were set. +EOF + +test_with_helper 'Insufficient priority vs handshake failed: 2/2' < OK +protocol_set_enabled TLS1.3 -> OK +connect -> handshake failed: A TLS fatal alert has been received. +EOF +# TLS 1.3 does some masquerading as TLS 1.2, I guess, so it's not +# handshake failed: A packet with illegal or unsupported version was received. + terminate_proc ${SERVER_PID} ### Tests against a NORMAL server (all three TLS versions enabled) eval "${GETPORT}" # server is launched without allowlisting config file in effect -launch_server -d9 --echo --priority NORMAL \ +launch_server --echo --priority NORMAL \ --x509keyfile "${TMPFILE_KEY}" --x509certfile "${TMPFILE_CERT}" SERVER_PID=$! wait_server ${SERVER_PID} -# !!! CURRENTLY NOT WORKING AS EXPECTED !!! -# smoke-test enabling with protocol_set -#test_with_helper < connection established: (TLS1.2)-(RSA)-(AES-128-GCM) -#protocol_set_enabled TLS1.3 -> OK -#connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM) -#EOF +# sanity-test +test_with_helper 'sanity test against liberal server' < connection established: (TLS1.2)-(RSA)-(AES-128-GCM) +EOF -# !!! CURRENTLY NOT WORKING AS EXPECTED !!! -# ["gnutls_protocol_set_enabled enables, TLS"] -# with a configuration file not allowlisting a specific TLS protocol version, -# enabling that version with gnutls_protocol_set_enabled -# allows connecting to a server accepting this TLS protocol version alone -#test_with_helper < connection established: (TLS1.2)-(RSA)-(AES-128-GCM) -#protocol_set_enabled TLS1.3 -> OK -#connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM) -#EOF +test_with_helper 'smoke-test enabling' < OK +connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM) +EOF -# !!! CURRENTLY NOT WORKING AS EXPECTED !!! -# ["gnutls_protocol_set_enabled enables revertibly, TLS"] -# consecutive gnutls_protocol_set -# can prevent the client from connecting (with a different session handle) -#test_with_helper < connection established: (TLS1.2)-(RSA)-(AES-128-GCM) -#protocol_set_enabled TLS1.1 -> OK -#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) -#protocol_set_disabled TLS1.2 -> OK -#connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) -#protocol_set_disabled TLS1.1 -> OK -#connect -> bad priority: No or insufficient priorities were set. -#EOF -# Alternative one -#test_with_helper < connection established: (TLS1.2)-(RSA)-(AES-128-GCM) -#protocol_set_enabled TLS1.3 -> OK -#connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM) -#protocol_set_disabled TLS1.3 -> OK -#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) -#EOF +test_with_helper 'going down to TLS1.1' < OK +protocol_set_disabled TLS1.2 -> OK +connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) +EOF -# !!! CURRENTLY NOT WORKING AS EXPECTED !!! -# ["gnutls_protocol_set_disabled disables selectively, TLS"] -# gnutls_protocol_set_disabled with a specific version -# doesn't disable other previously enabled version. -# ["gnutls_protocol_set_enabled enables selectively, TLS"] -# gnutls_protocol_set_enabled enabling a specific version -# doesn't enable other previously disabled version. -#test_with_helper < connection established: (TLS1.2)-(RSA)-(AES-128-GCM) -#protocol_set_enabled TLS1.3 -> OK -#protocol_set_enabled TLS1.2 -> OK -#protocol_set_enabled TLS1.1 -> OK -#connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM) -#protocol_set_disabled TLS1.3 -> OK -#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) -#protocol_set_disabled TLS1.2 -> OK -#connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) -#protocol_set_disabled TLS1.1 -> OK -#connect -> bad priority: No or insufficient priorities were set. -#protocol_set_enabled TLS1.1 -> OK -#connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) -#protocol_set_enabled TLS1.2 -> OK -#connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) -#protocol_set_enabled TLS1.3 -> OK -#connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM) -#EOF +test_with_helper 'going up to TLS 1.3' < OK +connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM) +EOF + +test_with_helper 'useless toggles' < OK +protocol_set_disabled TLS1.2 -> OK +protocol_set_enabled TLS1.2 -> OK +protocol_set_enabled TLS1.1 -> OK +protocol_set_enabled TLS1.1 -> OK +protocol_set_enabled TLS1.3 -> OK +protocol_set_disabled TLS1.1 -> OK +protocol_set_disabled TLS1.3 -> OK +connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) +EOF + +test_with_helper 'disable does not overdisable: 1/2' < OK +protocol_set_enabled TLS1.2 -> OK +protocol_set_enabled TLS1.1 -> OK +protocol_set_disabled TLS1.3 -> OK +protocol_set_disabled TLS1.1 -> OK +connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) +EOF + +test_with_helper 'disable does not overdisable: 2/2' < OK +protocol_set_enabled TLS1.2 -> OK +protocol_set_enabled TLS1.1 -> OK +protocol_set_disabled TLS1.3 -> OK +protocol_set_disabled TLS1.2 -> OK +connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) +EOF terminate_proc ${SERVER_PID} -### Tests against a TLS 1.1 & 1.3 server (1.2 disabled) +#### Tests against a TLS 1.3 server +# +eval "${GETPORT}" +# server is launched without allowlisting config file in effect +launch_server --echo \ + --priority "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3" \ + --x509keyfile "${TMPFILE_KEY}" --x509certfile "${TMPFILE_CERT}" +SERVER_PID=$! +wait_server ${SERVER_PID} + +test_with_helper 'sanity negative' < handshake failed: A TLS fatal alert has been received. +protocol_set_enabled TLS1.3 -> INVALID_REQUEST +protocol_set_enabled TLS1.1 -> INVALID_REQUEST +protocol_set_disabled TLS1.2 -> INVALID_REQUEST +connect -> handshake failed: A TLS fatal alert has been received. +EOF + +test_with_helper 'enable 1.3' < OK +connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM) +EOF + +test_with_helper 'enable 1.3 only' < OK +protocol_set_enabled TLS1.3 -> OK +connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM) +EOF + +test_with_helper 'enable 1.1' < OK +connect -> handshake failed: A TLS fatal alert has been received. +EOF +# A special case according to a comment in set_ciphersuite_list: +# > we require TLS1.2 to be enabled if TLS1.3 is asked for, and +# > a pre-TLS1.2 protocol is there; that is because servers which +# > do not support TLS1.3 will negotiate TLS1.2 if seen a TLS1.3 handshake +test_with_helper 'enable 1.1 and 1.3 only - does not work as you expect' < OK +protocol_set_disabled TLS1.2 -> OK +protocol_set_enabled TLS1.1 -> OK +connect -> handshake failed: A packet with illegal or unsupported version was received. +EOF + +test_with_helper 'enable 1.1 and 1.3' < OK +protocol_set_enabled TLS1.1 -> OK +connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM) +EOF + +test_with_helper 'enable 1.1 and 1.3, different order' < OK +protocol_set_enabled TLS1.3 -> OK +connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM) +EOF + +terminate_proc ${SERVER_PID} + +#### Tests against a TLS 1.1 + TLS 1.2 server +# eval "${GETPORT}" # server is launched without allowlisting config file in effect -launch_server -d9 --echo \ - --priority "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.1:+VERS-TLS1.3" \ +launch_server --echo \ + --priority "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.1:+VERS-TLS1.2" \ --x509keyfile "${TMPFILE_KEY}" --x509certfile "${TMPFILE_CERT}" SERVER_PID=$! wait_server ${SERVER_PID} -# !!! CURRENTLY NOT WORKING AS EXPECTED !!! -#test_with_helper < handshake failed: A packet with illegal or unsupported version was received. -#protocol_set_enabled TLS1.1 -> OK -#connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) -#protocol_set_enabled TLS1.3 -> OK -#connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM) -#protocol_set_disabled TLS1.3 -> OK -#connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) -#protocol_set_disabled TLS1.1 -> OK -#connect -> handshake failed: A packet with illegal or unsupported version was received. -#protocol_set_disabled TLS1.2 -> OK -#connect -> bad priority: No or insufficient priorities were set. -#EOF +test_with_helper 'sanity 1.2' < connection established: (TLS1.2)-(RSA)-(AES-128-GCM) +EOF + +test_with_helper 'enable 1.1' < OK +connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM) +EOF + +test_with_helper 'enable 1.1 only' < OK +protocol_set_disabled TLS1.2 -> OK +connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) +EOF + +test_with_helper 'enable 1.1 and 1.3 only' < OK +protocol_set_disabled TLS1.2 -> OK +protocol_set_enabled TLS1.1 -> OK +connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) +EOF + +test_with_helper 'enable 1.1 and 1.3 only, different order' < OK +protocol_set_disabled TLS1.2 -> OK +protocol_set_enabled TLS1.3 -> OK +connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1) +EOF terminate_proc ${SERVER_PID} diff --git a/tests/suite/tls-interoperability b/tests/suite/tls-interoperability new file mode 160000 index 0000000000..fd76ba1868 --- /dev/null +++ b/tests/suite/tls-interoperability @@ -0,0 +1 @@ +Subproject commit fd76ba18687e684f656bb3cf7a37fcb93b4e1f0f diff --git a/tests/tls13/compress-cert-cli.c b/tests/tls13/compress-cert-cli.c new file mode 100644 index 0000000000..f4e66bf313 --- /dev/null +++ b/tests/tls13/compress-cert-cli.c @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2022 Red Hat, Inc. + * + * Author: Daiki Ueno + * + * This file is part of GnuTLS. + * + * GnuTLS is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuTLS 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 a copy of the GNU Lesser General Public License + * along with this program. If not, see + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cert-common.h" + +#include "utils.h" +#include "eagain-common.h" + +const char *side = ""; + +static void tls_log_func(int level, const char *str) +{ + fprintf(stderr, "%s|<%d>| %s", side, level, str); +} + +struct handshake_cb_data_st { + bool is_server; + bool found_compress_certificate; + bool found_compressed_certificate; + bool found_certificate; +}; + +static int ext_callback(void *ctx, unsigned tls_id, const unsigned char *data, unsigned size) +{ + struct handshake_cb_data_st *cb_data = ctx; + if (tls_id == 27) { /* compress_certificate */ + cb_data->found_compress_certificate = 1; + } + return 0; +} + +#define SKIP8(pos, total) { \ + uint8_t _s; \ + if (pos+1 > total) fail("error\n"); \ + _s = msg->data[pos]; \ + if ((size_t)(pos+1+_s) > total) fail("error\n"); \ + pos += 1+_s; \ + } + +static int +handshake_callback(gnutls_session_t session, unsigned int htype, + unsigned post, unsigned int incoming, + const gnutls_datum_t *msg) +{ + struct handshake_cb_data_st *data = gnutls_session_get_ptr(session); + unsigned pos = 0; + gnutls_datum_t mmsg; + int ret; + + if ((data->is_server && incoming) || + (!data->is_server && !incoming)) { + return 0; + } + + switch (htype) { + case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST: + SKIP8(pos, msg->size); + + mmsg.data = &msg->data[pos]; + mmsg.size = msg->size - pos; + ret = gnutls_ext_raw_parse(data, ext_callback, &mmsg, 0); + assert(ret >= 0); + break; + case GNUTLS_HANDSHAKE_COMPRESSED_CERTIFICATE_PKT: + data->found_compressed_certificate = true; + break; + case GNUTLS_HANDSHAKE_CERTIFICATE_PKT: + data->found_certificate = true; + break; + default: + break; + } + + return 0; +} + +static void run(void) +{ + /* Server stuff. */ + gnutls_certificate_credentials_t scred; + gnutls_session_t server; + gnutls_compression_method_t smethods[] = { + GNUTLS_COMP_ZSTD, GNUTLS_COMP_BROTLI, GNUTLS_COMP_ZLIB + }; + struct handshake_cb_data_st sdata = { 0, false, false, false }; + int sret; + /* Client stuff. */ + gnutls_certificate_credentials_t ccred; + gnutls_session_t client; + gnutls_compression_method_t cmethods[] = { + GNUTLS_COMP_ZLIB, GNUTLS_COMP_BROTLI + }; + struct handshake_cb_data_st cdata = { 0, false, false, false }; + int cret; + /* Need to enable anonymous KX specifically. */ + int ret; + + /* General init. */ + global_init(); + gnutls_global_set_log_function(tls_log_func); + if (debug) + gnutls_global_set_log_level(9); + + /* Init server */ + assert(gnutls_certificate_allocate_credentials(&scred) >= 0); + assert(gnutls_certificate_set_x509_key_mem(scred, + &server_ca3_localhost_cert, + &server_ca3_key, + GNUTLS_X509_FMT_PEM) >= 0); + assert(gnutls_certificate_set_x509_trust_mem(scred, + &ca3_cert, + GNUTLS_X509_FMT_PEM) >= 0); + + assert(gnutls_init(&server, GNUTLS_SERVER) >= 0); + gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST); + ret = + gnutls_priority_set_direct(server, + "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3", + NULL); + if (ret < 0) + exit(1); + + ret = gnutls_compress_certificate_set_methods(server, smethods, sizeof(smethods)/sizeof(*smethods)); + if (ret < 0) { + fail("server: setting compression method failed (%s)\n", + gnutls_strerror(ret)); + } + sdata.is_server = true; + gnutls_session_set_ptr(server, &sdata); + gnutls_handshake_set_hook_function(server, GNUTLS_HANDSHAKE_ANY, + GNUTLS_HOOK_POST, + handshake_callback); + + gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, scred); + gnutls_transport_set_push_function(server, server_push); + gnutls_transport_set_pull_function(server, server_pull); + gnutls_transport_set_ptr(server, server); + + /* Init client */ + assert(gnutls_certificate_allocate_credentials(&ccred) >= 0); + assert(gnutls_certificate_set_x509_key_mem + (ccred, &cli_ca3_cert_chain, &cli_ca3_key, GNUTLS_X509_FMT_PEM) >= 0); + assert(gnutls_certificate_set_x509_trust_mem + (ccred, &ca3_cert, GNUTLS_X509_FMT_PEM) >= 0); + + gnutls_init(&client, GNUTLS_CLIENT); + ret = + gnutls_priority_set_direct(client, + "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3", + NULL); + assert(ret >= 0); + + ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, ccred); + if (ret < 0) + exit(1); + + ret = gnutls_compress_certificate_set_methods(client, cmethods, sizeof(cmethods)/sizeof(*cmethods)); + if (ret < 0) { + fail("client: setting compression method failed (%s)\n", + gnutls_strerror(ret)); + } + cdata.is_server = false; + gnutls_session_set_ptr(client, &cdata); + gnutls_handshake_set_hook_function(client, GNUTLS_HANDSHAKE_ANY, + GNUTLS_HOOK_POST, + handshake_callback); + + gnutls_transport_set_push_function(client, client_push); + gnutls_transport_set_pull_function(client, client_pull); + gnutls_transport_set_ptr(client, client); + + + HANDSHAKE(client, server); + if (debug) + success("Handshake established\n"); + + if (!sdata.found_compress_certificate) { + fail("server: compress_certificate extension not sent\n"); + } + if (!sdata.found_compressed_certificate) { + fail("server: CompressedCertificate not sent\n"); + } + if (sdata.found_certificate) { + fail("server: Certificate sent\n"); + } + if (!cdata.found_compress_certificate) { + fail("client: compress_certificate extension not received\n"); + } + if (!cdata.found_compressed_certificate) { + fail("client: CompressedCertificate not received\n"); + } + if (cdata.found_certificate) { + fail("client: Certificate not received\n"); + } + + gnutls_bye(client, GNUTLS_SHUT_WR); + gnutls_bye(server, GNUTLS_SHUT_WR); + + gnutls_deinit(client); + gnutls_deinit(server); + + gnutls_certificate_free_credentials(scred); + gnutls_certificate_free_credentials(ccred); + + gnutls_global_deinit(); + reset_buffers(); +} + +void doit(void) +{ +#if !defined(HAVE_LIBZ) || !defined(HAVE_LIBBROTLI) || !defined(HAVE_LIBZSTD) + exit(77); +#endif + run(); +}