summaryrefslogtreecommitdiffstats
path: root/meta/recipes-connectivity/openssl
diff options
context:
space:
mode:
authorWilliam Lyu <William.Lyu@windriver.com>2023-11-01 09:37:41 -0400
committerRichard Purdie <richard.purdie@linuxfoundation.org>2023-11-05 11:28:31 +0000
commit02d38393d1904b44f3d08efb72a9cc3c446e74fe (patch)
treee3fb3c6bd500dce89f5d850ea65a3ab9f0149867 /meta/recipes-connectivity/openssl
parentc395a9f9f715f908415d215bfc131bb5eba04ab8 (diff)
downloadpoky-02d38393d1904b44f3d08efb72a9cc3c446e74fe.tar.gz
openssl: improve handshake test error reporting
Fixes [YOCTO #15225] Yocto Bug #15255 is not reproducible. To obtain more useful information for debugging, the OpenSSL test code is improved so that more detailed state information in the handshake loop is printed when an error occurs. (From OE-Core rev: 5bf9a70f580357badd01f39822998985654b0bfc) Signed-off-by: William Lyu <William.Lyu@windriver.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-connectivity/openssl')
-rw-r--r--meta/recipes-connectivity/openssl/openssl/0001-Added-handshake-history-reporting-when-test-fails.patch374
-rw-r--r--meta/recipes-connectivity/openssl/openssl_3.1.4.bb1
2 files changed, 375 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/openssl/openssl/0001-Added-handshake-history-reporting-when-test-fails.patch b/meta/recipes-connectivity/openssl/openssl/0001-Added-handshake-history-reporting-when-test-fails.patch
new file mode 100644
index 0000000000..aa2e5bb800
--- /dev/null
+++ b/meta/recipes-connectivity/openssl/openssl/0001-Added-handshake-history-reporting-when-test-fails.patch
@@ -0,0 +1,374 @@
1From 5ba65051fea0513db0d997f0ab7cafb9826ed74a Mon Sep 17 00:00:00 2001
2From: William Lyu <William.Lyu@windriver.com>
3Date: Fri, 20 Oct 2023 16:22:37 -0400
4Subject: [PATCH] Added handshake history reporting when test fails
5
6Upstream-Status: Submitted [https://github.com/openssl/openssl/pull/22481]
7
8Signed-off-by: William Lyu <William.Lyu@windriver.com>
9---
10 test/helpers/handshake.c | 139 +++++++++++++++++++++++++++++----------
11 test/helpers/handshake.h | 70 +++++++++++++++++++-
12 test/ssl_test.c | 44 +++++++++++++
13 3 files changed, 218 insertions(+), 35 deletions(-)
14
15diff --git a/test/helpers/handshake.c b/test/helpers/handshake.c
16index e0422469e4..ae2ad59dd4 100644
17--- a/test/helpers/handshake.c
18+++ b/test/helpers/handshake.c
19@@ -1,5 +1,5 @@
20 /*
21- * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
22+ * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
23 *
24 * Licensed under the Apache License 2.0 (the "License"). You may not use
25 * this file except in compliance with the License. You can obtain a copy
26@@ -24,6 +24,102 @@
27 #include <netinet/sctp.h>
28 #endif
29
30+/* Shamelessly copied from test/helpers/ssl_test_ctx.c */
31+/* Maps string names to various enumeration type */
32+typedef struct {
33+ const char *name;
34+ int value;
35+} enum_name_map;
36+
37+static const enum_name_map connect_phase_names[] = {
38+ {"Handshake", HANDSHAKE},
39+ {"RenegAppData", RENEG_APPLICATION_DATA},
40+ {"RenegSetup", RENEG_SETUP},
41+ {"RenegHandshake", RENEG_HANDSHAKE},
42+ {"AppData", APPLICATION_DATA},
43+ {"Shutdown", SHUTDOWN},
44+ {"ConnectionDone", CONNECTION_DONE}
45+};
46+
47+static const enum_name_map peer_status_names[] = {
48+ {"PeerSuccess", PEER_SUCCESS},
49+ {"PeerRetry", PEER_RETRY},
50+ {"PeerError", PEER_ERROR},
51+ {"PeerWaiting", PEER_WAITING},
52+ {"PeerTestFail", PEER_TEST_FAILURE}
53+};
54+
55+static const enum_name_map handshake_status_names[] = {
56+ {"HandshakeSuccess", HANDSHAKE_SUCCESS},
57+ {"ClientError", CLIENT_ERROR},
58+ {"ServerError", SERVER_ERROR},
59+ {"InternalError", INTERNAL_ERROR},
60+ {"HandshakeRetry", HANDSHAKE_RETRY}
61+};
62+
63+/* Shamelessly copied from test/helpers/ssl_test_ctx.c */
64+static const char *enum_name(const enum_name_map *enums, size_t num_enums,
65+ int value)
66+{
67+ size_t i;
68+ for (i = 0; i < num_enums; i++) {
69+ if (enums[i].value == value) {
70+ return enums[i].name;
71+ }
72+ }
73+ return "InvalidValue";
74+}
75+
76+const char *handshake_connect_phase_name(connect_phase_t phase)
77+{
78+ return enum_name(connect_phase_names, OSSL_NELEM(connect_phase_names),
79+ (int)phase);
80+}
81+
82+const char *handshake_status_name(handshake_status_t handshake_status)
83+{
84+ return enum_name(handshake_status_names, OSSL_NELEM(handshake_status_names),
85+ (int)handshake_status);
86+}
87+
88+const char *handshake_peer_status_name(peer_status_t peer_status)
89+{
90+ return enum_name(peer_status_names, OSSL_NELEM(peer_status_names),
91+ (int)peer_status);
92+}
93+
94+static void save_loop_history(HANDSHAKE_HISTORY *history,
95+ connect_phase_t phase,
96+ handshake_status_t handshake_status,
97+ peer_status_t server_status,
98+ peer_status_t client_status,
99+ int client_turn_count,
100+ int is_client_turn)
101+{
102+ HANDSHAKE_HISTORY_ENTRY *new_entry = NULL;
103+
104+ /*
105+ * Create a new history entry for a handshake loop with statuses given in
106+ * the arguments. Potentially evicting the oldest entry when the
107+ * ring buffer is full.
108+ */
109+ ++(history->last_idx);
110+ history->last_idx &= MAX_HANDSHAKE_HISTORY_ENTRY_IDX_MASK;
111+
112+ new_entry = &((history->entries)[history->last_idx]);
113+ new_entry->phase = phase;
114+ new_entry->handshake_status = handshake_status;
115+ new_entry->server_status = server_status;
116+ new_entry->client_status = client_status;
117+ new_entry->client_turn_count = client_turn_count;
118+ new_entry->is_client_turn = is_client_turn;
119+
120+ /* Evict the oldest handshake loop entry when the ring buffer is full. */
121+ if (history->entry_count < MAX_HANDSHAKE_HISTORY_ENTRY) {
122+ ++(history->entry_count);
123+ }
124+}
125+
126 HANDSHAKE_RESULT *HANDSHAKE_RESULT_new(void)
127 {
128 HANDSHAKE_RESULT *ret;
129@@ -719,15 +815,6 @@ static void configure_handshake_ssl(SSL *server, SSL *client,
130 SSL_set_post_handshake_auth(client, 1);
131 }
132
133-/* The status for each connection phase. */
134-typedef enum {
135- PEER_SUCCESS,
136- PEER_RETRY,
137- PEER_ERROR,
138- PEER_WAITING,
139- PEER_TEST_FAILURE
140-} peer_status_t;
141-
142 /* An SSL object and associated read-write buffers. */
143 typedef struct peer_st {
144 SSL *ssl;
145@@ -1074,17 +1161,6 @@ static void do_shutdown_step(PEER *peer)
146 }
147 }
148
149-typedef enum {
150- HANDSHAKE,
151- RENEG_APPLICATION_DATA,
152- RENEG_SETUP,
153- RENEG_HANDSHAKE,
154- APPLICATION_DATA,
155- SHUTDOWN,
156- CONNECTION_DONE
157-} connect_phase_t;
158-
159-
160 static int renegotiate_op(const SSL_TEST_CTX *test_ctx)
161 {
162 switch (test_ctx->handshake_mode) {
163@@ -1162,19 +1238,6 @@ static void do_connect_step(const SSL_TEST_CTX *test_ctx, PEER *peer,
164 }
165 }
166
167-typedef enum {
168- /* Both parties succeeded. */
169- HANDSHAKE_SUCCESS,
170- /* Client errored. */
171- CLIENT_ERROR,
172- /* Server errored. */
173- SERVER_ERROR,
174- /* Peers are in inconsistent state. */
175- INTERNAL_ERROR,
176- /* One or both peers not done. */
177- HANDSHAKE_RETRY
178-} handshake_status_t;
179-
180 /*
181 * Determine the handshake outcome.
182 * last_status: the status of the peer to have acted last.
183@@ -1539,6 +1602,10 @@ static HANDSHAKE_RESULT *do_handshake_internal(
184
185 start = time(NULL);
186
187+ save_loop_history(&(ret->history),
188+ phase, status, server.status, client.status,
189+ client_turn_count, client_turn);
190+
191 /*
192 * Half-duplex handshake loop.
193 * Client and server speak to each other synchronously in the same process.
194@@ -1560,6 +1627,10 @@ static HANDSHAKE_RESULT *do_handshake_internal(
195 0 /* server went last */);
196 }
197
198+ save_loop_history(&(ret->history),
199+ phase, status, server.status, client.status,
200+ client_turn_count, client_turn);
201+
202 switch (status) {
203 case HANDSHAKE_SUCCESS:
204 client_turn_count = 0;
205diff --git a/test/helpers/handshake.h b/test/helpers/handshake.h
206index 78b03f9f4b..b9967c2623 100644
207--- a/test/helpers/handshake.h
208+++ b/test/helpers/handshake.h
209@@ -1,5 +1,5 @@
210 /*
211- * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
212+ * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
213 *
214 * Licensed under the Apache License 2.0 (the "License"). You may not use
215 * this file except in compliance with the License. You can obtain a copy
216@@ -12,6 +12,11 @@
217
218 #include "ssl_test_ctx.h"
219
220+#define MAX_HANDSHAKE_HISTORY_ENTRY_BIT 4
221+#define MAX_HANDSHAKE_HISTORY_ENTRY (1 << MAX_HANDSHAKE_HISTORY_ENTRY_BIT)
222+#define MAX_HANDSHAKE_HISTORY_ENTRY_IDX_MASK \
223+ ((1 << MAX_HANDSHAKE_HISTORY_ENTRY_BIT) - 1)
224+
225 typedef struct ctx_data_st {
226 unsigned char *npn_protocols;
227 size_t npn_protocols_len;
228@@ -22,6 +27,63 @@ typedef struct ctx_data_st {
229 char *session_ticket_app_data;
230 } CTX_DATA;
231
232+typedef enum {
233+ HANDSHAKE,
234+ RENEG_APPLICATION_DATA,
235+ RENEG_SETUP,
236+ RENEG_HANDSHAKE,
237+ APPLICATION_DATA,
238+ SHUTDOWN,
239+ CONNECTION_DONE
240+} connect_phase_t;
241+
242+/* The status for each connection phase. */
243+typedef enum {
244+ PEER_SUCCESS,
245+ PEER_RETRY,
246+ PEER_ERROR,
247+ PEER_WAITING,
248+ PEER_TEST_FAILURE
249+} peer_status_t;
250+
251+typedef enum {
252+ /* Both parties succeeded. */
253+ HANDSHAKE_SUCCESS,
254+ /* Client errored. */
255+ CLIENT_ERROR,
256+ /* Server errored. */
257+ SERVER_ERROR,
258+ /* Peers are in inconsistent state. */
259+ INTERNAL_ERROR,
260+ /* One or both peers not done. */
261+ HANDSHAKE_RETRY
262+} handshake_status_t;
263+
264+/* Stores the various status information in a handshake loop. */
265+typedef struct handshake_history_entry_st {
266+ connect_phase_t phase;
267+ handshake_status_t handshake_status;
268+ peer_status_t server_status;
269+ peer_status_t client_status;
270+ int client_turn_count;
271+ int is_client_turn;
272+} HANDSHAKE_HISTORY_ENTRY;
273+
274+typedef struct handshake_history_st {
275+ /* Implemented using ring buffer. */
276+ /*
277+ * The valid entries are |entries[last_idx]|, |entries[last_idx-1]|,
278+ * ..., etc., going up to |entry_count| number of entries. Note that when
279+ * the index into the array |entries| becomes < 0, we wrap around to
280+ * the end of |entries|.
281+ */
282+ HANDSHAKE_HISTORY_ENTRY entries[MAX_HANDSHAKE_HISTORY_ENTRY];
283+ /* The number of valid entries in |entries| array. */
284+ size_t entry_count;
285+ /* The index of the last valid entry in the |entries| array. */
286+ size_t last_idx;
287+} HANDSHAKE_HISTORY;
288+
289 typedef struct handshake_result {
290 ssl_test_result_t result;
291 /* These alerts are in the 2-byte format returned by the info_callback. */
292@@ -77,6 +139,8 @@ typedef struct handshake_result {
293 char *cipher;
294 /* session ticket application data */
295 char *result_session_ticket_app_data;
296+ /* handshake loop history */
297+ HANDSHAKE_HISTORY history;
298 } HANDSHAKE_RESULT;
299
300 HANDSHAKE_RESULT *HANDSHAKE_RESULT_new(void);
301@@ -95,4 +159,8 @@ int configure_handshake_ctx_for_srp(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
302 CTX_DATA *server2_ctx_data,
303 CTX_DATA *client_ctx_data);
304
305+const char *handshake_connect_phase_name(connect_phase_t phase);
306+const char *handshake_status_name(handshake_status_t handshake_status);
307+const char *handshake_peer_status_name(peer_status_t peer_status);
308+
309 #endif /* OSSL_TEST_HANDSHAKE_HELPER_H */
310diff --git a/test/ssl_test.c b/test/ssl_test.c
311index ea608518f9..9d6b093c81 100644
312--- a/test/ssl_test.c
313+++ b/test/ssl_test.c
314@@ -26,6 +26,44 @@ static OSSL_LIB_CTX *libctx = NULL;
315 /* Currently the section names are of the form test-<number>, e.g. test-15. */
316 #define MAX_TESTCASE_NAME_LENGTH 100
317
318+static void print_handshake_history(const HANDSHAKE_HISTORY *history)
319+{
320+ size_t first_idx;
321+ size_t i;
322+ size_t cur_idx;
323+ const HANDSHAKE_HISTORY_ENTRY *cur_entry;
324+ const char header_template[] = "|%14s|%16s|%16s|%16s|%17s|%14s|";
325+ const char body_template[] = "|%14s|%16s|%16s|%16s|%17d|%14s|";
326+
327+ TEST_info("The following is the server/client state "
328+ "in the most recent %d handshake loops.",
329+ MAX_HANDSHAKE_HISTORY_ENTRY);
330+
331+ TEST_note("=================================================="
332+ "==================================================");
333+ TEST_note(header_template,
334+ "phase", "handshake status", "server status",
335+ "client status", "client turn count", "is client turn");
336+ TEST_note("+--------------+----------------+----------------"
337+ "+----------------+-----------------+--------------+");
338+
339+ first_idx = (history->last_idx - history->entry_count + 1) &
340+ MAX_HANDSHAKE_HISTORY_ENTRY_IDX_MASK;
341+ for (i = 0; i < history->entry_count; ++i) {
342+ cur_idx = (first_idx + i) & MAX_HANDSHAKE_HISTORY_ENTRY_IDX_MASK;
343+ cur_entry = &(history->entries)[cur_idx];
344+ TEST_note(body_template,
345+ handshake_connect_phase_name(cur_entry->phase),
346+ handshake_status_name(cur_entry->handshake_status),
347+ handshake_peer_status_name(cur_entry->server_status),
348+ handshake_peer_status_name(cur_entry->client_status),
349+ cur_entry->client_turn_count,
350+ cur_entry->is_client_turn ? "true" : "false");
351+ }
352+ TEST_note("=================================================="
353+ "==================================================");
354+}
355+
356 static const char *print_alert(int alert)
357 {
358 return alert ? SSL_alert_desc_string_long(alert) : "no alert";
359@@ -388,6 +426,12 @@ static int check_test(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx)
360 ret &= check_client_sign_type(result, test_ctx);
361 ret &= check_client_ca_names(result, test_ctx);
362 }
363+
364+ /* Print handshake loop history if any check fails. */
365+ if (!ret) {
366+ print_handshake_history(&(result->history));
367+ }
368+
369 return ret;
370 }
371
372--
3732.25.1
374
diff --git a/meta/recipes-connectivity/openssl/openssl_3.1.4.bb b/meta/recipes-connectivity/openssl/openssl_3.1.4.bb
index e4b20e4a40..c6c70a1213 100644
--- a/meta/recipes-connectivity/openssl/openssl_3.1.4.bb
+++ b/meta/recipes-connectivity/openssl/openssl_3.1.4.bb
@@ -13,6 +13,7 @@ SRC_URI = "http://www.openssl.org/source/openssl-${PV}.tar.gz \
13 file://0001-Configure-do-not-tweak-mips-cflags.patch \ 13 file://0001-Configure-do-not-tweak-mips-cflags.patch \
14 file://fix_random_labels.patch \ 14 file://fix_random_labels.patch \
15 file://0001-Link-libatomic-on-riscv32.patch \ 15 file://0001-Link-libatomic-on-riscv32.patch \
16 file://0001-Added-handshake-history-reporting-when-test-fails.patch \
16 " 17 "
17 18
18SRC_URI:append:class-nativesdk = " \ 19SRC_URI:append:class-nativesdk = " \