xref: /openbsd-src/regress/lib/libssl/client/clienttest.c (revision fbffb3299c3edc0e008406dc9acac58f5594204c)
1 /*
2  * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <openssl/ssl.h>
18 
19 #include <openssl/dtls1.h>
20 #include <openssl/ssl3.h>
21 
22 #include <err.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 #define DTLS_HM_OFFSET (DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH)
27 #define DTLS_RANDOM_OFFSET (DTLS_HM_OFFSET + 2)
28 #define DTLS_CIPHER_OFFSET (DTLS_HM_OFFSET + 38)
29 
30 #define SSL3_HM_OFFSET (SSL3_RT_HEADER_LENGTH + SSL3_HM_HEADER_LENGTH)
31 #define SSL3_RANDOM_OFFSET (SSL3_HM_OFFSET + 2)
32 #define SSL3_CIPHER_OFFSET (SSL3_HM_OFFSET + 37)
33 
34 static unsigned char cipher_list_dtls1[] = {
35 	0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85,
36 	0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84,
37 	0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45,
38 	0x00, 0x2f, 0x00, 0x41, 0xc0, 0x12, 0xc0, 0x08,
39 	0x00, 0x16, 0x00, 0x0a, 0x00, 0xff,
40 };
41 
42 static unsigned char client_hello_dtls1[] = {
43 	0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
44 	0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00,
45 	0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 	0x54, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
47 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xc0,
51 	0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00,
52 	0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0,
53 	0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00,
54 	0x2f, 0x00, 0x41, 0xc0, 0x12, 0xc0, 0x08, 0x00,
55 	0x16, 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00,
56 	0x04, 0x00, 0x23, 0x00, 0x00,
57 };
58 
59 static unsigned char cipher_list_tls10[] = {
60 	0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85,
61 	0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84,
62 	0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45,
63 	0x00, 0x2f, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07,
64 	0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08,
65 	0x00, 0x16, 0x00, 0x0a, 0x00, 0xff,
66 };
67 
68 static unsigned char client_hello_tls10[] = {
69 	0x16, 0x03, 0x01, 0x00, 0x71, 0x01, 0x00, 0x00,
70 	0x6d, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
71 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 	0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xc0, 0x14,
75 	0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88,
76 	0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x13,
77 	0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 0x2f,
78 	0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05,
79 	0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16,
80 	0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, 0x16,
81 	0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a,
82 	0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17,
83 	0x00, 0x18, 0x00, 0x23, 0x00, 0x00,
84 };
85 
86 static unsigned char cipher_list_tls11[] = {
87 	0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85,
88 	0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84,
89 	0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45,
90 	0x00, 0x2f, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07,
91 	0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08,
92 	0x00, 0x16, 0x00, 0x0a, 0x00, 0xff,
93 };
94 
95 static unsigned char client_hello_tls11[] = {
96 	0x16, 0x03, 0x01, 0x00, 0x71, 0x01, 0x00, 0x00,
97 	0x6d, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
98 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 	0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xc0, 0x14,
102 	0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88,
103 	0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x13,
104 	0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 0x2f,
105 	0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05,
106 	0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16,
107 	0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, 0x16,
108 	0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a,
109 	0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17,
110 	0x00, 0x18, 0x00, 0x23, 0x00, 0x00,
111 };
112 
113 static unsigned char cipher_list_tls12_aes[] = {
114 	0xc0, 0x30, 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24,
115 	0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b,
116 	0x00, 0x39, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa,
117 	0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81,
118 	0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0,
119 	0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27,
120 	0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e,
121 	0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45,
122 	0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba,
123 	0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05,
124 	0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16,
125 	0x00, 0x0a, 0x00, 0xff,
126 };
127 
128 static unsigned char cipher_list_tls12_chacha[] = {
129 	0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30,
130 	0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14,
131 	0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39,
132 	0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81,
133 	0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0,
134 	0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27,
135 	0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e,
136 	0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45,
137 	0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba,
138 	0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05,
139 	0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16,
140 	0x00, 0x0a, 0x00, 0xff,
141 };
142 
143 static unsigned char client_hello_tls12[] = {
144 	0x16, 0x03, 0x01, 0x00, 0xc5, 0x01, 0x00, 0x00,
145 	0xc1, 0x03, 0x03, 0xc9, 0xf9, 0x1f, 0x05, 0xaf,
146 	0x61, 0xd7, 0xe7, 0x84, 0xd1, 0x1c, 0x6f, 0x79,
147 	0x32, 0x04, 0x8e, 0x5c, 0xe3, 0x18, 0x5a, 0x85,
148 	0xee, 0x44, 0xe1, 0xca, 0x32, 0xce, 0x07, 0xd3,
149 	0xdb, 0x0f, 0x91, 0x00, 0x00, 0x5c, 0xc0, 0x30,
150 	0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14,
151 	0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39,
152 	0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xff, 0x85,
153 	0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d,
154 	0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 0x00, 0x84,
155 	0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23,
156 	0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67,
157 	0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c,
158 	0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 0x00, 0x41,
159 	0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 0x00, 0x04,
160 	0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a,
161 	0x00, 0xff, 0x01, 0x00, 0x00, 0x3c, 0x00, 0x0b,
162 	0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08,
163 	0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
164 	0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x22,
165 	0x00, 0x20, 0x08, 0x06, 0x06, 0x01, 0x06, 0x03,
166 	0xef, 0xef, 0x08, 0x05, 0x05, 0x01, 0x05, 0x03,
167 	0x08, 0x04, 0x04, 0x01, 0x04, 0x03, 0xee, 0xee,
168 	0xed, 0xed, 0x03, 0x01, 0x03, 0x03, 0x02, 0x01,
169 	0x02, 0x03,
170 };
171 
172 struct client_hello_test {
173 	const unsigned char *desc;
174 	const int protocol;
175 	const size_t random_start;
176 	const SSL_METHOD *(*ssl_method)(void);
177 	const long ssl_options;
178 };
179 
180 static struct client_hello_test client_hello_tests[] = {
181 	{
182 		.desc = "DTLSv1 client",
183 		.protocol = DTLS1_VERSION,
184 		.random_start = DTLS_RANDOM_OFFSET,
185 		.ssl_method = DTLSv1_client_method,
186 	},
187 	{
188 		.desc = "TLSv1 client",
189 		.protocol = TLS1_VERSION,
190 		.random_start = SSL3_RANDOM_OFFSET,
191 		.ssl_method = TLSv1_client_method,
192 	},
193 	{
194 		.desc = "TLSv1_1 client",
195 		.protocol = TLS1_1_VERSION,
196 		.random_start = SSL3_RANDOM_OFFSET,
197 		.ssl_method = TLSv1_1_client_method,
198 	},
199 	{
200 		.desc = "TLSv1_2 client",
201 		.protocol = TLS1_2_VERSION,
202 		.random_start = SSL3_RANDOM_OFFSET,
203 		.ssl_method = TLSv1_2_client_method,
204 	},
205 	{
206 		.desc = "SSLv23 default",
207 		.protocol = TLS1_2_VERSION,
208 		.random_start = SSL3_RANDOM_OFFSET,
209 		.ssl_method = SSLv23_client_method,
210 		.ssl_options = 0,
211 	},
212 	{
213 		.desc = "SSLv23 (no TLSv1.2)",
214 		.protocol = TLS1_1_VERSION,
215 		.random_start = SSL3_RANDOM_OFFSET,
216 		.ssl_method = SSLv23_client_method,
217 		.ssl_options = SSL_OP_NO_TLSv1_2,
218 	},
219 	{
220 		.desc = "SSLv23 (no TLSv1.1)",
221 		.protocol = TLS1_VERSION,
222 		.random_start = SSL3_RANDOM_OFFSET,
223 		.ssl_method = SSLv23_client_method,
224 		.ssl_options = SSL_OP_NO_TLSv1_1,
225 	},
226 	{
227 		.desc = "TLS default",
228 		.protocol = TLS1_2_VERSION,
229 		.random_start = SSL3_RANDOM_OFFSET,
230 		.ssl_method = TLS_client_method,
231 		.ssl_options = 0,
232 	},
233 	{
234 		.desc = "TLS (no TLSv1.2)",
235 		.protocol = TLS1_1_VERSION,
236 		.random_start = SSL3_RANDOM_OFFSET,
237 		.ssl_method = TLS_client_method,
238 		.ssl_options = SSL_OP_NO_TLSv1_2,
239 	},
240 	{
241 		.desc = "TLS (no TLSv1.1)",
242 		.protocol = TLS1_VERSION,
243 		.random_start = SSL3_RANDOM_OFFSET,
244 		.ssl_method = TLS_client_method,
245 		.ssl_options = SSL_OP_NO_TLSv1_1,
246 	},
247 	{
248 		.desc = "TLS (no TLSv1.0, no TLSv1.1)",
249 		.protocol = TLS1_2_VERSION,
250 		.random_start = SSL3_RANDOM_OFFSET,
251 		.ssl_method = TLS_client_method,
252 		.ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1,
253 	},
254 };
255 
256 #define N_CLIENT_HELLO_TESTS \
257     (sizeof(client_hello_tests) / sizeof(*client_hello_tests))
258 
259 static void
260 hexdump(const unsigned char *buf, size_t len)
261 {
262 	size_t i;
263 
264 	for (i = 1; i <= len; i++)
265 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
266 
267 	fprintf(stderr, "\n");
268 }
269 
270 static inline int
271 ssl_aes_is_accelerated(void)
272 {
273 #if defined(__i386__) || defined(__x86_64__)
274 	return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0);
275 #else
276 	return (0);
277 #endif
278 }
279 
280 static int
281 make_client_hello(int protocol, char **out, size_t *outlen)
282 {
283 	size_t client_hello_len, cipher_list_len, cipher_list_offset;
284 	const char *client_hello, *cipher_list;
285 	char *p;
286 
287 	*out = NULL;
288 	*outlen = 0;
289 
290 	switch (protocol) {
291 	case DTLS1_VERSION:
292 		client_hello = client_hello_dtls1;
293 		client_hello_len = sizeof(client_hello_dtls1);
294 		cipher_list = cipher_list_dtls1;
295 		cipher_list_len = sizeof(cipher_list_dtls1);
296 		cipher_list_offset = DTLS_CIPHER_OFFSET;
297 		break;
298 
299 	case TLS1_VERSION:
300 		client_hello = client_hello_tls10;
301 		client_hello_len = sizeof(client_hello_tls10);
302 		cipher_list = cipher_list_tls10;
303 		cipher_list_len = sizeof(cipher_list_tls10);
304 		cipher_list_offset = SSL3_CIPHER_OFFSET;
305 		break;
306 
307 	case TLS1_1_VERSION:
308 		client_hello = client_hello_tls11;
309 		client_hello_len = sizeof(client_hello_tls11);
310 		cipher_list = cipher_list_tls11;
311 		cipher_list_len = sizeof(cipher_list_tls11);
312 		cipher_list_offset = SSL3_CIPHER_OFFSET;
313 		break;
314 
315 	case TLS1_2_VERSION:
316 		client_hello = client_hello_tls12;
317 		client_hello_len = sizeof(client_hello_tls12);
318 		if (ssl_aes_is_accelerated() == 1)
319 			cipher_list = cipher_list_tls12_aes;
320 		else
321 			cipher_list = cipher_list_tls12_chacha;
322 		cipher_list_len = sizeof(cipher_list_tls12_chacha);
323 		cipher_list_offset = SSL3_CIPHER_OFFSET;
324 		break;
325 
326 	default:
327 		return (-1);
328 	}
329 
330 	if ((p = malloc(client_hello_len)) == NULL)
331 		return (-1);
332 
333 	memcpy(p, client_hello, client_hello_len);
334 	memcpy(p + cipher_list_offset, cipher_list, cipher_list_len);
335 
336 	*out = p;
337 	*outlen = client_hello_len;
338 
339 	return (0);
340 }
341 
342 static int
343 client_hello_test(int testno, struct client_hello_test *cht)
344 {
345 	BIO *rbio = NULL, *wbio = NULL;
346 	SSL_CTX *ssl_ctx = NULL;
347 	SSL *ssl = NULL;
348 	char *client_hello = NULL;
349 	size_t client_hello_len;
350 	char *wbuf, rbuf[1];
351 	int ret = 1;
352 	size_t i;
353 	long len;
354 
355 	fprintf(stderr, "Test %i - %s\n", testno, cht->desc);
356 
357 	/* Providing a small buf causes *_get_server_hello() to return. */
358 	if ((rbio = BIO_new_mem_buf(rbuf, sizeof(rbuf))) == NULL) {
359 		fprintf(stderr, "Failed to setup rbio\n");
360 		goto failure;
361 	}
362 	if ((wbio = BIO_new(BIO_s_mem())) == NULL) {
363 		fprintf(stderr, "Failed to setup wbio\n");
364 		goto failure;
365 	}
366 
367 	if ((ssl_ctx = SSL_CTX_new(cht->ssl_method())) == NULL) {
368 		fprintf(stderr, "SSL_CTX_new() returned NULL\n");
369 		goto failure;
370 	}
371 
372 	SSL_CTX_set_options(ssl_ctx, cht->ssl_options);
373 
374 	if ((ssl = SSL_new(ssl_ctx)) == NULL) {
375 		fprintf(stderr, "SSL_new() returned NULL\n");
376 		goto failure;
377 	}
378 
379 	rbio->references = 2;
380 	wbio->references = 2;
381 
382 	SSL_set_bio(ssl, rbio, wbio);
383 
384 	if (SSL_connect(ssl) != 0) {
385 		fprintf(stderr, "SSL_connect() returned non-zero\n");
386 		goto failure;
387 	}
388 
389 	len = BIO_get_mem_data(wbio, &wbuf);
390 
391 	if (make_client_hello(cht->protocol, &client_hello,
392 	    &client_hello_len) != 0)
393 		goto failure;
394 
395 	if ((size_t)len != client_hello_len) {
396 		fprintf(stderr, "FAIL: test returned ClientHello length %li, "
397 		    "want %zu\n", len, client_hello_len);
398 		fprintf(stderr, "received:\n");
399 		hexdump(wbuf, len);
400 		goto failure;
401 	}
402 
403 	/* We expect the client random to differ. */
404 	i = cht->random_start + SSL3_RANDOM_SIZE;
405 	if (memcmp(client_hello, wbuf, cht->random_start) != 0 ||
406 	    memcmp(&client_hello[cht->random_start],
407 		&wbuf[cht->random_start], SSL3_RANDOM_SIZE) == 0 ||
408 	    memcmp(&client_hello[i], &wbuf[i], len - i) != 0) {
409 		fprintf(stderr, "FAIL: ClientHello differs:\n");
410 		fprintf(stderr, "received:\n");
411 		memset(&wbuf[cht->random_start], 0, SSL3_RANDOM_SIZE);
412 		hexdump(wbuf, len);
413 		fprintf(stderr, "test data:\n");
414 		hexdump(client_hello, client_hello_len);
415 		fprintf(stderr, "\n");
416 		goto failure;
417 	}
418 
419 	ret = 0;
420 
421 failure:
422 	SSL_CTX_free(ssl_ctx);
423 	SSL_free(ssl);
424 
425 	rbio->references = 1;
426 	wbio->references = 1;
427 
428 	BIO_free(rbio);
429 	BIO_free(wbio);
430 
431 	free(client_hello);
432 
433 	return (ret);
434 }
435 
436 int
437 main(int argc, char **argv)
438 {
439 	int failed = 0;
440 	size_t i;
441 
442 	SSL_library_init();
443 
444 	for (i = 0; i < N_CLIENT_HELLO_TESTS; i++)
445 		failed |= client_hello_test(i, &client_hello_tests[i]);
446 
447 	return (failed);
448 }
449