File: test_libcrypto_interning.sh

package info (click to toggle)
aws-crt-python 0.20.4%2Bdfsg-1~bpo12%2B1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-backports
  • size: 72,656 kB
  • sloc: ansic: 381,805; python: 23,008; makefile: 6,251; sh: 4,536; cpp: 699; ruby: 208; java: 77; perl: 73; javascript: 46; xml: 11
file content (176 lines) | stat: -rwxr-xr-x 6,727 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/usr/bin/env bash
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# A copy of the License is located at
#
#  http://aws.amazon.com/apache2.0
#
# or in the "license" file accompanying this file. This file is distributed
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied. See the License for the specific language governing
# permissions and limitations under the License.
#

set -e

source codebuild/bin/s2n_setup_env.sh
source codebuild/bin/jobs.sh

# build 2 different version of libcrypto to make it easy to break the application if
# interning doesn't work as expected
WHICH_LIBCRYPTO=$(echo "${S2N_LIBCRYPTO:-"openssl-1.1.1"}")
TARGET_LIBCRYPTO="${WHICH_LIBCRYPTO//[-.]/_}"
TARGET_LIBCRYPTO_PATH="${TEST_DEPS_DIR}/${WHICH_LIBCRYPTO}"
OPENSSL_1_0="$OPENSSL_1_0_2_INSTALL_DIR"
if [ ! -f $OPENSSL_1_0/lib/libcrypto.a ]; then
  ./codebuild/bin/install_openssl_1_0_2.sh $OPENSSL_1_0/src $OPENSSL_1_0 linux
fi
if [ ! -f $TARGET_LIBCRYPTO_PATH/lib/libcrypto.a ]; then
  if [ "$TARGET_LIBCRYPTO" == "awslc" ]; then
    ./codebuild/bin/install_${TARGET_LIBCRYPTO}.sh $TARGET_LIBCRYPTO_PATH/src $TARGET_LIBCRYPTO_PATH 0
  else
    ./codebuild/bin/install_${TARGET_LIBCRYPTO}.sh $TARGET_LIBCRYPTO_PATH/src $TARGET_LIBCRYPTO_PATH linux
  fi
fi

COMMON_FLAGS="-DCMAKE_PREFIX_PATH=$TARGET_LIBCRYPTO_PATH -DCMAKE_BUILD_TYPE=RelWithDebInfo"
LTO_FLAGS="-DS2N_LTO=on"

# use LTO-aware commands if possible
if [ -x "$(command -v gcc-ar)" ]; then
  LTO_FLAGS+=" -DCMAKE_AR=$(which gcc-ar) -DCMAKE_NM=$(which gcc-nm) -DCMAKE_RANLIB=$(which gcc-ranlib)"
fi

function fail() {
    echo "test failure: $1"
    exit 1
}

function write_app() {
cat <<EOF > $1
#include <s2n.h>
#include <openssl/bn.h>

int main() {
    s2n_init();
    BN_CTX_new();
    return 0;
}
EOF
}

function build() {
  echo "=== BUILDING $1 ==="
  cmake . -B$1 $COMMON_FLAGS ${@:2}
  cmake --build $1 -- -j $JOBS
}

function tests() {
  echo "=== TESTING $1 ==="
  make -C $1 test ARGS="-j $JOBS -L unit"
}

##################
# Dynamic builds #
##################

# build a default version to test what happens without interning
build build/shared-default -DBUILD_SHARED_LIBS=on -DBUILD_TESTING=on
ldd ./build/shared-default/lib/libs2n.so | grep -q libcrypto || fail "shared-default: libcrypto was not linked"

# ensure libcrypto interning works with shared libs and no testing
build build/shared -DBUILD_SHARED_LIBS=on -DBUILD_TESTING=off -DS2N_INTERN_LIBCRYPTO=on
# s2n should not publicly depend on libcrypto
ldd ./build/shared/lib/libs2n.so | grep -q libcrypto && fail "shared: libcrypto was not interned"

# ensure libcrypto interning works with shared libs, LTO and no testing
# NOTE: interning+LTO+testing doesn't currently work
build build/shared-lto -DBUILD_SHARED_LIBS=on -DBUILD_TESTING=off -DS2N_INTERN_LIBCRYPTO=on $LTO_FLAGS
# s2n should not publicly depend on libcrypto
ldd ./build/shared-lto/lib/libs2n.so | grep -q libcrypto && fail "shared-lto: libcrypto was not interned"

# ensure libcrypto interning works with shared libs and testing
build build/shared-testing -DBUILD_SHARED_LIBS=on -DBUILD_TESTING=on -DS2N_INTERN_LIBCRYPTO=on
# s2n should not publicly depend on libcrypto
ldd ./build/shared-testing/lib/libs2n.so | grep -q libcrypto && fail "shared-testing: libcrypto was not interned"
# run the tests and make sure they all pass with the prefixed version
tests build/shared-testing
# load the wrong version of libcrypto and the tests should still pass
LD_PRELOAD=$OPENSSL_1_0/lib/libcrypto.so tests build/shared-testing

# ensure the small app will compile with both versions of openssl without any linking issues
for build in shared shared-lto; do
  # create a small app that links against both s2n and libcrypto
  write_app build/$build/app.c

  for target in $OPENSSL_1_0 $TARGET_LIBCRYPTO_PATH; do
    echo "testing $build linking with $target"
    mkdir -p $target/bin
    cc -fPIE -Iapi -I$target/include build/$build/app.c build/$build/lib/libs2n.so $target/lib/libcrypto.a -lpthread -ldl -o $target/bin/test-app
    # make sure the app doesn't crash
    LD_LIBRARY_PATH="build/$build/lib:$target/lib:$LD_LIBRARY_PATH" $target/bin/test-app
  done
done

##################
# Static builds  #
##################

# ensure libcrypto interning works with static libs
# NOTE: static builds don't vary based on testing being enabled
build build/static -DBUILD_SHARED_LIBS=off -DBUILD_TESTING=on -DS2N_INTERN_LIBCRYPTO=on
tests build/static

# TODO figure out how to get static-lto+interning builds working

# ensure the small app will compile with both versions of openssl without any linking issues
for build in static; do
  # create a small app that links against both s2n and libcrypto
  write_app build/$build/app.c

  for target in $OPENSSL_1_0 $TARGET_LIBCRYPTO_PATH; do
    echo "testing $build linking with $target"
    mkdir -p $target/bin
    cc -fPIE -Iapi -I$target/include build/$build/app.c build/$build/lib/libs2n.a $target/lib/libcrypto.a -lpthread -ldl -o $target/bin/test-app
    nm $target/bin/test-app | grep -q 'T s2n$BN_CTX_new' || fail "$target: libcrypto symbols were not prefixed"
    nm $target/bin/test-app | grep -q 'T BN_CTX_new' || fail "$target: libcrypto was not linked in application"
    # make sure the app doesn't crash
    $target/bin/test-app
  done
done

##################
# Runtime tests  #
##################

run_connection_test() {
    local TARGET="$1"
    
    LD_PRELOAD=$OPENSSL_1_0/lib/libcrypto.so ./build/$TARGET/bin/s2nd -c default_tls13 localhost 4433 &> /dev/null &
    local SERVER_PID=$!
    
    # Wait for the server to start up before connecting
    sleep 5s
    
    LD_PRELOAD=$OPENSSL_1_0/lib/libcrypto.so ./build/$TARGET/bin/s2nc -i -c default_tls13 localhost 4433 | tee build/client.log
    kill $SERVER_PID &> /dev/null || true

    # ensure a TLS 1.3 session was negotiated
    echo "checking for TLS 1.3"
    grep -q "Actual protocol version: 34" build/client.log
}

# without interning, the connection should fail when linking the wrong version of libcrypto
echo "Running test: attempt TLS1.3 handshake without interning"
run_connection_test shared-default && fail "TLS 1.3 handshake was expected to fail"
echo "TLS1.3 handshake failed as expected"
echo ""

# with interning, the connection should succeed even though we've linked the wrong version of libcrypto
echo "Running test: attempt TLS1.3 handshake with interning"
run_connection_test shared-testing || fail "TLS 1.3 handshake was expected to succeed"
echo "TLS1.3 handshake succeeded as expected"

echo "SUCCESS!"