Skip to content

Commit

Permalink
(FIPS Backport) Add EVP_md_null and SSL_set_ciphersuites (#1637) (#1653)
Browse files Browse the repository at this point in the history
  • Loading branch information
WillChilds-Klein authored Jun 21, 2024
1 parent 32ed1f6 commit 41c106d
Show file tree
Hide file tree
Showing 10 changed files with 243 additions and 1 deletion.
25 changes: 25 additions & 0 deletions .github/workflows/integrations.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Integration tests
on:
push:
branches: [ '*' ]
pull_request:
branches: [ '*' ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: true
env:
CC: gcc
jobs:
openldap:
if: github.repository_owner == 'aws'
runs-on: ubuntu-latest
name: OpenLDAP
steps:
- name: Install OS Dependencies
run: |
sudo apt-get update
sudo apt-get -y --no-install-recommends install cmake gcc ninja-build golang make
- uses: actions/checkout@v3
- name: Build AWS-LC, build openldap, run tests
run: |
./tests/ci/run_openldap_integration.sh master OPENLDAP_REL_ENG_2_5
19 changes: 19 additions & 0 deletions crypto/digest_extra/digest_extra.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,22 @@ static const EVP_MD evp_md_blake2b256 = {
};

const EVP_MD *EVP_blake2b256(void) { return &evp_md_blake2b256; }

static void null_init(EVP_MD_CTX *ctx) {}

static void null_update(EVP_MD_CTX *ctx, const void *data, size_t count) {}

static void null_final(EVP_MD_CTX *ctx, unsigned char *md) {}

static const EVP_MD evp_md_null = {
NID_undef,
0,
0,
null_init,
null_update,
null_final,
0,
sizeof(EVP_MD_CTX),
};

const EVP_MD *EVP_md_null(void) { return &evp_md_null; }
5 changes: 5 additions & 0 deletions crypto/digest_extra/digest_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ static const MD sha3_384 = { "SHA3-384", &EVP_sha3_384, &SHA3_384 };
static const MD sha3_512 = { "SHA3-512", &EVP_sha3_512, &SHA3_512 };
static const MD md5_sha1 = { "MD5-SHA1", &EVP_md5_sha1, nullptr };
static const MD blake2b256 = { "BLAKE2b-256", &EVP_blake2b256, nullptr };
static const MD md_null = { "NULL", &EVP_md_null, nullptr };

struct DigestTestVector {
// md is the digest to test.
Expand Down Expand Up @@ -224,6 +225,10 @@ static const DigestTestVector kTestVectors[] = {
// BLAKE2b-256 tests.
{blake2b256, "abc", 1,
"bddd813c634239723171ef3fee98579b94964e3bb1cb3e427262c8c068d52319"},

// NULL tests. Empty output for any input
{md_null, "abc", 1, ""},
{md_null, "", 1, ""},
};

static void CompareDigest(const DigestTestVector *test,
Expand Down
4 changes: 4 additions & 0 deletions include/openssl/digest.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,10 @@ struct env_md_ctx_st {
} /* EVP_MD_CTX */;


// EVP_md_null is a "null" message digest that does nothing: i.e. the hash it
// returns is of zero length. Included for OpenSSL compatibility
OPENSSL_EXPORT const EVP_MD *EVP_md_null(void);

#if defined(__cplusplus)
} // extern C

Expand Down
8 changes: 8 additions & 0 deletions include/openssl/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1546,6 +1546,14 @@ OPENSSL_EXPORT int SSL_set_strict_cipher_list(SSL *ssl, const char *str);
// evaluating |str| as a cipher string. It returns one on success and zero on failure.
OPENSSL_EXPORT int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);

// SSL_set_ciphersuites sets the available TLSv1.3 ciphersuites on an |ssl|,
// returning one on success and zero on failure. In OpenSSL, the only
// difference between |SSL_CTX_set_ciphersuites| and |SSL_set_ciphersuites| is
// that the latter copies the |SSL|'s |cipher_list| to its associated
// |SSL_CONNECTION|. In AWS-LC, we track everything on the |ssl|'s |config| so
// duplication is not necessary.
OPENSSL_EXPORT int SSL_set_ciphersuites(SSL *ssl, const char *str);

// SSL_set_cipher_list configures the cipher list for |ssl|, evaluating |str| as
// a cipher string. It returns one on success and zero on failure.
//
Expand Down
9 changes: 9 additions & 0 deletions ssl/ssl_lib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2057,6 +2057,15 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) {
true /* only configure TLSv1.3 ciphers */);
}

int SSL_set_ciphersuites(SSL *ssl, const char *str) {
if (!ssl->config) {
return 0;
}
return ssl_create_cipher_list(&ssl->config->cipher_list, str,
false /* not strict */,
true /* configure TLSv1.3 ciphers */);
}

int SSL_set_strict_cipher_list(SSL *ssl, const char *str) {
if (!ssl->config) {
return 0;
Expand Down
15 changes: 14 additions & 1 deletion ssl/ssl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -876,10 +876,14 @@ TEST(SSLTest, TLSv13CipherRules) {
SCOPED_TRACE(t.rule);
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
ASSERT_TRUE(ctx);
bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
ASSERT_TRUE(ssl);

// Test lax mode.
ASSERT_TRUE(SSL_CTX_set_ciphersuites(ctx.get(), t.rule));
EXPECT_TRUE(CipherListsEqual(ctx.get(), t.expected, true /* TLSv1.3 only */))
ASSERT_TRUE(SSL_set_ciphersuites(ssl.get(), t.rule));
EXPECT_TRUE(
CipherListsEqual(ctx.get(), t.expected, true /* TLSv1.3 only */))
<< "Cipher rule evaluated to:\n"
<< CipherListToString(ctx.get(), true /* TLSv1.3 only */);

Expand All @@ -890,17 +894,23 @@ TEST(SSLTest, TLSv13CipherRules) {
SCOPED_TRACE(rule);
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
ASSERT_TRUE(ctx);
bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
ASSERT_TRUE(ssl);

EXPECT_FALSE(SSL_CTX_set_ciphersuites(ctx.get(), rule));
EXPECT_FALSE(SSL_set_ciphersuites(ssl.get(), rule));
ERR_clear_error();
}

for (const char *rule : kTLSv13MustNotIncludeNull) {
SCOPED_TRACE(rule);
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
ASSERT_TRUE(ctx);
bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
ASSERT_TRUE(ssl);

ASSERT_TRUE(SSL_CTX_set_ciphersuites(ctx.get(), rule));
ASSERT_TRUE(SSL_set_ciphersuites(ssl.get(), rule));
// Currenly, only three TLSv1.3 ciphers are supported.
EXPECT_EQ(3u, sk_SSL_CIPHER_num(tls13_ciphers(ctx.get())));
for (const SSL_CIPHER *cipher : tls13_ciphers(ctx.get())) {
Expand All @@ -918,8 +928,11 @@ TEST(SSLTest, TLSv13CipherRules) {
SCOPED_TRACE(t.rule);
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
ASSERT_TRUE(ctx);
bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
ASSERT_TRUE(ssl);

EXPECT_FALSE(SSL_CTX_set_ciphersuites(ctx.get(), t.rule));
EXPECT_FALSE(SSL_set_ciphersuites(ssl.get(), t.rule));
ASSERT_EQ(ERR_GET_REASON(ERR_get_error()), SSL_R_NO_CIPHER_MATCH);
ERR_clear_error();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--- ./servers/slapd/main.c 2024-01-29 18:53:15.000000000 +0000
+++ ./servers/slapd/main.c 2024-01-29 18:22:49.300948791 +0000
@@ -43,6 +43,8 @@
#include "slapi/slapi.h"
#endif

+#include <openssl/crypto.h>
+
#ifdef LDAP_SIGCHLD
static RETSIGTYPE wait4child( int sig );
#endif
@@ -764,6 +766,8 @@

if ( version ) {
fprintf( stderr, "%s\n", Versionstr );
+ fprintf( stderr, "COMPILE OPENSSL VERSION: %s\n", OPENSSL_VERSION_TEXT);
+ fprintf( stderr, "RUNTIME OPENSSL VERSION: %s\n", OpenSSL_version(OPENSSL_VERSION));
if ( version > 2 ) {
if ( slap_oinfo[0].ov_type ) {
fprintf( stderr, "Included static overlays:\n");
20 changes: 20 additions & 0 deletions tests/ci/openldap_patch/master/print-libcrypto-info.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--- ./servers/slapd/main.c 2024-01-29 18:53:15.000000000 +0000
+++ ./servers/slapd/main.c 2024-01-29 18:22:49.300948791 +0000
@@ -43,6 +43,8 @@
#include "slapi/slapi.h"
#endif

+#include <openssl/crypto.h>
+
#ifdef LDAP_SIGCHLD
static RETSIGTYPE wait4child( int sig );
#endif
@@ -764,6 +766,8 @@

if ( version ) {
fprintf( stderr, "%s\n", Versionstr );
+ fprintf( stderr, "COMPILE OPENSSL VERSION: %s\n", OPENSSL_VERSION_TEXT);
+ fprintf( stderr, "RUNTIME OPENSSL VERSION: %s\n", OpenSSL_version(OPENSSL_VERSION));
if ( version > 2 ) {
if ( slap_oinfo[0].ov_type ) {
fprintf( stderr, "Included static overlays:\n");
119 changes: 119 additions & 0 deletions tests/ci/run_openldap_integration.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#!/usr/bin/env bash
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0 OR ISC

set -exu

source tests/ci/common_posix_setup.sh

set -exuo pipefail

# Set up environment.

# SYS_ROOT
# - SRC_ROOT(aws-lc)
# - SCRATCH_FOLDER
# - OPENLDAP_SRC_FOLDER
# - main
# ...
# - OPENLDAP_PATCH_FOLDER
# - main
# ...
# - AWS_LC_BUILD_FOLDER
# - AWS_LC_INSTALL_FOLDER

# Assumes script is executed from the root of aws-lc directory
SCRATCH_FOLDER="${SRC_ROOT}/OPENLDAP_BUILD_ROOT"
OPENLDAP_SRC_FOLDER="${SCRATCH_FOLDER}/openldap-src"
OPENLDAP_PATCH_FOLDER="${SRC_ROOT}/tests/ci/openldap_patch"
AWS_LC_BUILD_FOLDER="${SCRATCH_FOLDER}/aws-lc-build"
AWS_LC_INSTALL_FOLDER="${SCRATCH_FOLDER}/aws-lc-install"

AWS_LC_DIR=$(pwd)
function aws_lc_build() {
${CMAKE_COMMAND} ${AWS_LC_DIR} -GNinja "-B${AWS_LC_BUILD_FOLDER}" "-DCMAKE_INSTALL_PREFIX=${AWS_LC_INSTALL_FOLDER}"
ninja -C ${AWS_LC_BUILD_FOLDER} install
ls -R ${AWS_LC_INSTALL_FOLDER}
rm -rf ${AWS_LC_BUILD_FOLDER}/*
}

function openldap_build() {
local branch=${1}
pushd ${branch}
# Modify CFLAGS and LDFLAGS so compiler and linker can find AWS-LC's artifacts
export STRICT_C_COMPILER="gcc"
export CPPFLAGS="-I$AWS_LC_INSTALL_FOLDER/include"
export LDFLAGS="$AWS_LC_INSTALL_FOLDER/lib/libcrypto.a $AWS_LC_INSTALL_FOLDER/lib/libssl.a"
export LDFLAGS="$LDFLAGS -L$AWS_LC_INSTALL_FOLDER/lib"
./configure \
--prefix=$AWS_LC_INSTALL_FOLDER \
--enable-debug \
--enable-static \
--enable-slapd \
--disable-syslog \
--with-tls \
--without-systemd
make -j ${NUM_CPU_THREADS}
# assert that neither libcrypto nor libssl are linked dynamically
ldd ./servers/slapd/slapd | grep libcrypto || true | wc -l | xargs test 0 -eq
ldd ./servers/slapd/slapd | grep libssl || true | wc -l | xargs test 0 -eq
# assert that patched slapd binary is compiled against and linked to AWS-LC
# for some reason, -V exits non-zero so use "true" to guard against pipefail
( ./servers/slapd/slapd -V || true ) |& grep AWS-LC | wc -l | xargs test 2 -eq
popd
}

function openldap_run_tests() {
local branch=${1}
pushd ${branch}
make -j ${NUM_CPU_THREADS} test
popd
}

function openldap_patch() {
local branch=${1}
local src_dir="${OPENLDAP_SRC_FOLDER}/${branch}"
local patch_dir="${OPENLDAP_PATCH_FOLDER}/${branch}"
if [[ ! $(find -L ${patch_dir} -type f -name '*.patch') ]]; then
echo "No patch for ${branch}!"
exit 1
fi
git clone https://github.com/openldap/openldap.git ${src_dir} \
--depth 1 \
--branch ${branch}
for patchfile in $(find -L ${patch_dir} -type f -name '*.patch'); do
echo "Apply patch ${patchfile}..."
cat ${patchfile} \
| patch -p1 --quiet -d ${src_dir}
done
}

if [[ "$#" -eq "0" ]]; then
echo "No openldap branches provided for testing"
exit 1
fi

mkdir -p ${SCRATCH_FOLDER}
rm -rf ${SCRATCH_FOLDER}/*
cd ${SCRATCH_FOLDER}

mkdir -p ${AWS_LC_BUILD_FOLDER} ${AWS_LC_INSTALL_FOLDER}

aws_lc_build ${SRC_ROOT} ${AWS_LC_BUILD_FOLDER} ${AWS_LC_INSTALL_FOLDER} \
-DBUILD_TESTING=OFF \
-DBUILD_SHARED_LIBS=0

# Some systems install under "lib64" instead of "lib"
ln -s ${AWS_LC_INSTALL_FOLDER}/lib64 ${AWS_LC_INSTALL_FOLDER}/lib

mkdir -p ${OPENLDAP_SRC_FOLDER}
pushd ${OPENLDAP_SRC_FOLDER}

# NOTE: As we add more versions to support, we may want to parallelize here
for branch in "$@"; do
openldap_patch ${branch}
openldap_build ${branch}
openldap_run_tests ${branch}
done

popd

0 comments on commit 41c106d

Please sign in to comment.