Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-30578

go-toolset: SHA functions do not use FIPS compliant openssl APIs

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Normal Normal
    • None
    • rhel-9.5
    • go-toolset
    • None
    • None
    • 6
    • rhel-sst-pt-llvm-rust-go
    • ssg_platform_tools
    • 3
    • Dev ack
    • False
    • Hide

      None

      Show
      None
    • Yes
    • Sprint 5, Sprint 6, Sprint 7, SST LLVM/Rust/Go Sprint 8, SST LLVM/Rust/Go Sprint 9, SST LLVM/Rust/Go Sprint 10
    • None
    • None
    • Unspecified Release Note Type - Unknown
    • None

      What are you experiencing? What are you expecting to happen?

      In the go-toolet the functions in sha.go are all using the deprecated low level API calls in openssl. These do not go via the fips provider and so are not FIPS compliant. See:

      https://github.com/golang/go/blob/25aa45afcf40ff6c699b47bad0cb609bba84da12/src/crypto/internal/boring/sha.go#L16 for an example.

      Ran `fips-mode-setup enable` and rebooted my server and then with the following go code:

       

      result2 := sha1.Sum([]byte("hash me"))
      fmt.Printf("%x\n", result2)

      I executed: `LD_DEBUG=symbols /tmp/test` and got:

      ...
      3880446: calling init: /usr/lib64/ossl-modules/fips.so
      3880446: 
      3880446: symbol=OSSL_provider_init; lookup in file=/usr/lib64/ossl-modules/fips.so [0]
      3880446: symbol=pthread_mutex_init; lookup in file=/tmp/test [0]
      3880446: symbol=pthread_mutex_init; lookup in file=/lib64/libresolv.so.2 [0]
      3880446: symbol=pthread_mutex_init; lookup in file=/lib64/libc.so.6 [0]
      3880446: symbol=SHA1_Init; lookup in file=/tmp/test [0]
      3880446: symbol=SHA1_Init; lookup in file=/lib64/libresolv.so.2 [0]
      3880446: symbol=SHA1_Init; lookup in file=/lib64/libc.so.6 [0]
      3880446: symbol=SHA1_Init; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
      3880446: symbol=SHA1_Init; lookup in file=/lib64/libcrypto.so.3 [0]
      3880446: symbol=SHA1_Update; lookup in file=/tmp/test [0]
      3880446: symbol=SHA1_Update; lookup in file=/lib64/libresolv.so.2 [0]
      3880446: symbol=SHA1_Update; lookup in file=/lib64/libc.so.6 [0]
      3880446: symbol=SHA1_Update; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
      3880446: symbol=SHA1_Update; lookup in file=/lib64/libcrypto.so.3 [0]
      3880446: symbol=SHA1_Final; lookup in file=/tmp/test [0]
      3880446: symbol=SHA1_Final; lookup in file=/lib64/libresolv.so.2 [0]
      3880446: symbol=SHA1_Final; lookup in file=/lib64/libc.so.6 [0]
      3880446: symbol=SHA1_Final; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
      3880446: symbol=SHA1_Final; lookup in file=/lib64/libcrypto.so.3 [0]

      Which shows it is using loading the FIPS module so is in FIPS mode, but then it uses the deprecated API calls for SHA1_ which the openssl fips documentation says do not use the fips module.

       

      On the page (https://www.openssl.org/docs/manmaster/man7/fips_module.html):

       

      Applications written to use the OpenSSL 3.0 FIPS module should not use any legacy APIs or features that avoid the FIPS module. Specifically this includes:
      Low level cryptographic APIs (use the high level APIs, such as EVP, instead)
      
      
      

      Instead of doing

       

      SHA1_Init
      SHA1_Update
      SHA1_Final

       

      We should be doing something like:

       

      const EVP_MD *md = EVP_get_digestbyname("sha256");
      if (md == NULL)
      { printf("Unknown message digest %s\n", "sha256"); exit(1); }
      EVP_MD_CTX *ctx = EVP_MD_CTX_new();
      if (!EVP_DigestInit_ex(ctx, md, NULL))
      { printf("Message digest initialization failed.\n"); ERR_print_errors_fp (stderr); EVP_MD_CTX_free(ctx); exit(1); }
      EVP_DigestUpdate(ctx, data, strlen(data));
      EVP_DigestFinal_ex(ctx, md_value, &md_len);
      

      This uses the high level EVP_ API and will be FIPS compliant.

      Also see https://github.com/openssl/openssl/blob/a4cbffcd8998180b98bb9f7ce6065ed37d079d8b/doc/man7/ossl-guide-migration.pod#L1105 where openssl say not to use functions such as `SHA1_Init` etc and instead use EVP. Apparently there are some convinience functions as well `..or the quick one-shot L<EVP_Q_digest(3)>`

      Note that for boringcrypto+boringssl the calls to SHA1_Init etc. are fine, as boringssl's API and openssl's API have diverged enough that SHA1_Init etc ar not deprecated APIs and are FIPS verified for boringssl, whereas for openssl SHA1_Init etc. are specifically called out as not using the FIPS module.

      Define the value or impact to you or the business
      FIPS conformance for our golang code in questionable.

      Where are you experiencing this behavior? What environment?
      Redhat 9, although it is the same on 8 as well.

      When does this behavior occur? Frequency? Repeatedly? At certain times?
      Always

              dueno@redhat.com Daiki Ueno
              rhn-support-smahanga Shreyas Mahangade
              David Benoit David Benoit
              Edjunior Machado Edjunior Machado
              Votes:
              1 Vote for this issue
              Watchers:
              13 Start watching this issue

                Created:
                Updated: