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