xref: /openbsd-src/usr.bin/openssl/s_cb.c (revision 23cc9d400791825fb9615b5c61d55ff2adb3056b)
1*23cc9d40Stb /* $OpenBSD: s_cb.c,v 1.22 2025/01/02 13:10:03 tb Exp $ */
2dab3f910Sjsing /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3dab3f910Sjsing  * All rights reserved.
4dab3f910Sjsing  *
5dab3f910Sjsing  * This package is an SSL implementation written
6dab3f910Sjsing  * by Eric Young (eay@cryptsoft.com).
7dab3f910Sjsing  * The implementation was written so as to conform with Netscapes SSL.
8dab3f910Sjsing  *
9dab3f910Sjsing  * This library is free for commercial and non-commercial use as long as
10dab3f910Sjsing  * the following conditions are aheared to.  The following conditions
11dab3f910Sjsing  * apply to all code found in this distribution, be it the RC4, RSA,
12dab3f910Sjsing  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13dab3f910Sjsing  * included with this distribution is covered by the same copyright terms
14dab3f910Sjsing  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15dab3f910Sjsing  *
16dab3f910Sjsing  * Copyright remains Eric Young's, and as such any Copyright notices in
17dab3f910Sjsing  * the code are not to be removed.
18dab3f910Sjsing  * If this package is used in a product, Eric Young should be given attribution
19dab3f910Sjsing  * as the author of the parts of the library used.
20dab3f910Sjsing  * This can be in the form of a textual message at program startup or
21dab3f910Sjsing  * in documentation (online or textual) provided with the package.
22dab3f910Sjsing  *
23dab3f910Sjsing  * Redistribution and use in source and binary forms, with or without
24dab3f910Sjsing  * modification, are permitted provided that the following conditions
25dab3f910Sjsing  * are met:
26dab3f910Sjsing  * 1. Redistributions of source code must retain the copyright
27dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer.
28dab3f910Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
29dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer in the
30dab3f910Sjsing  *    documentation and/or other materials provided with the distribution.
31dab3f910Sjsing  * 3. All advertising materials mentioning features or use of this software
32dab3f910Sjsing  *    must display the following acknowledgement:
33dab3f910Sjsing  *    "This product includes cryptographic software written by
34dab3f910Sjsing  *     Eric Young (eay@cryptsoft.com)"
35dab3f910Sjsing  *    The word 'cryptographic' can be left out if the rouines from the library
36dab3f910Sjsing  *    being used are not cryptographic related :-).
37dab3f910Sjsing  * 4. If you include any Windows specific code (or a derivative thereof) from
38dab3f910Sjsing  *    the apps directory (application code) you must include an acknowledgement:
39dab3f910Sjsing  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40dab3f910Sjsing  *
41dab3f910Sjsing  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42dab3f910Sjsing  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43dab3f910Sjsing  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44dab3f910Sjsing  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45dab3f910Sjsing  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46dab3f910Sjsing  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47dab3f910Sjsing  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48dab3f910Sjsing  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49dab3f910Sjsing  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50dab3f910Sjsing  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51dab3f910Sjsing  * SUCH DAMAGE.
52dab3f910Sjsing  *
53dab3f910Sjsing  * The licence and distribution terms for any publically available version or
54dab3f910Sjsing  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55dab3f910Sjsing  * copied and put under another distribution licence
56dab3f910Sjsing  * [including the GNU Public Licence.]
57dab3f910Sjsing  */
58dab3f910Sjsing /* ====================================================================
59dab3f910Sjsing  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
60dab3f910Sjsing  *
61dab3f910Sjsing  * Redistribution and use in source and binary forms, with or without
62dab3f910Sjsing  * modification, are permitted provided that the following conditions
63dab3f910Sjsing  * are met:
64dab3f910Sjsing  *
65dab3f910Sjsing  * 1. Redistributions of source code must retain the above copyright
66dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer.
67dab3f910Sjsing  *
68dab3f910Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
69dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer in
70dab3f910Sjsing  *    the documentation and/or other materials provided with the
71dab3f910Sjsing  *    distribution.
72dab3f910Sjsing  *
73dab3f910Sjsing  * 3. All advertising materials mentioning features or use of this
74dab3f910Sjsing  *    software must display the following acknowledgment:
75dab3f910Sjsing  *    "This product includes software developed by the OpenSSL Project
76dab3f910Sjsing  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77dab3f910Sjsing  *
78dab3f910Sjsing  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79dab3f910Sjsing  *    endorse or promote products derived from this software without
80dab3f910Sjsing  *    prior written permission. For written permission, please contact
81dab3f910Sjsing  *    openssl-core@openssl.org.
82dab3f910Sjsing  *
83dab3f910Sjsing  * 5. Products derived from this software may not be called "OpenSSL"
84dab3f910Sjsing  *    nor may "OpenSSL" appear in their names without prior written
85dab3f910Sjsing  *    permission of the OpenSSL Project.
86dab3f910Sjsing  *
87dab3f910Sjsing  * 6. Redistributions of any form whatsoever must retain the following
88dab3f910Sjsing  *    acknowledgment:
89dab3f910Sjsing  *    "This product includes software developed by the OpenSSL Project
90dab3f910Sjsing  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91dab3f910Sjsing  *
92dab3f910Sjsing  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93dab3f910Sjsing  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94dab3f910Sjsing  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95dab3f910Sjsing  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96dab3f910Sjsing  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97dab3f910Sjsing  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98dab3f910Sjsing  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99dab3f910Sjsing  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100dab3f910Sjsing  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101dab3f910Sjsing  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102dab3f910Sjsing  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103dab3f910Sjsing  * OF THE POSSIBILITY OF SUCH DAMAGE.
104dab3f910Sjsing  * ====================================================================
105dab3f910Sjsing  *
106dab3f910Sjsing  * This product includes cryptographic software written by Eric Young
107dab3f910Sjsing  * (eay@cryptsoft.com).  This product includes software written by Tim
108dab3f910Sjsing  * Hudson (tjh@cryptsoft.com).
109dab3f910Sjsing  *
110dab3f910Sjsing  */
111dab3f910Sjsing 
112dab3f910Sjsing #include <sys/socket.h>
113dab3f910Sjsing 
114dab3f910Sjsing #include <netinet/in.h>
115dab3f910Sjsing 
116dab3f910Sjsing #include <netdb.h>
117dab3f910Sjsing #include <stdio.h>
118dab3f910Sjsing #include <stdlib.h>
119dab3f910Sjsing #include <string.h>
120dab3f910Sjsing 
121dab3f910Sjsing #include "apps.h"
122dab3f910Sjsing 
123dab3f910Sjsing #include <openssl/err.h>
124dab3f910Sjsing #include <openssl/ssl.h>
125dab3f910Sjsing #include <openssl/x509.h>
126dab3f910Sjsing 
127dab3f910Sjsing #define	COOKIE_SECRET_LENGTH	16
128dab3f910Sjsing 
129dab3f910Sjsing int verify_depth = 0;
130dab3f910Sjsing int verify_return_error = 0;
131dab3f910Sjsing unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
132dab3f910Sjsing int cookie_initialized = 0;
133dab3f910Sjsing 
134dab3f910Sjsing int
135dab3f910Sjsing verify_callback(int ok, X509_STORE_CTX * ctx)
136dab3f910Sjsing {
137dab3f910Sjsing 	X509 *err_cert;
138dab3f910Sjsing 	int err, depth;
139dab3f910Sjsing 
140dab3f910Sjsing 	err_cert = X509_STORE_CTX_get_current_cert(ctx);
141dab3f910Sjsing 	err = X509_STORE_CTX_get_error(ctx);
142dab3f910Sjsing 	depth = X509_STORE_CTX_get_error_depth(ctx);
143dab3f910Sjsing 
144dab3f910Sjsing 	BIO_printf(bio_err, "depth=%d ", depth);
145dab3f910Sjsing 	if (err_cert) {
146dab3f910Sjsing 		X509_NAME_print_ex(bio_err, X509_get_subject_name(err_cert),
147dab3f910Sjsing 		    0, XN_FLAG_ONELINE);
148dab3f910Sjsing 		BIO_puts(bio_err, "\n");
149dab3f910Sjsing 	} else
150dab3f910Sjsing 		BIO_puts(bio_err, "<no cert>\n");
151dab3f910Sjsing 	if (!ok) {
152dab3f910Sjsing 		BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
153dab3f910Sjsing 		    X509_verify_cert_error_string(err));
154dab3f910Sjsing 		if (verify_depth >= depth) {
155dab3f910Sjsing 			if (!verify_return_error)
156dab3f910Sjsing 				ok = 1;
157dab3f910Sjsing 		} else {
158dab3f910Sjsing 			ok = 0;
159dab3f910Sjsing 		}
160dab3f910Sjsing 	}
161dab3f910Sjsing 	switch (err) {
162dab3f910Sjsing 	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
163dab3f910Sjsing 		BIO_puts(bio_err, "issuer= ");
1648e101a2aSdoug 		if (err_cert == NULL)
1658e101a2aSdoug 			BIO_puts(bio_err, "<error getting cert>");
1668e101a2aSdoug 		else
1678e101a2aSdoug 			X509_NAME_print_ex(bio_err,
1688e101a2aSdoug 			    X509_get_issuer_name(err_cert), 0, XN_FLAG_ONELINE);
169dab3f910Sjsing 		BIO_puts(bio_err, "\n");
170dab3f910Sjsing 		break;
171dab3f910Sjsing 	case X509_V_ERR_CERT_NOT_YET_VALID:
172dab3f910Sjsing 	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
173dab3f910Sjsing 		BIO_printf(bio_err, "notBefore=");
1748e101a2aSdoug 		if (err_cert == NULL)
1758e101a2aSdoug 			BIO_printf(bio_err, " <error getting cert>");
1768e101a2aSdoug 		else
177dab3f910Sjsing 			ASN1_TIME_print(bio_err, X509_get_notBefore(err_cert));
178dab3f910Sjsing 		BIO_printf(bio_err, "\n");
179dab3f910Sjsing 		break;
180dab3f910Sjsing 	case X509_V_ERR_CERT_HAS_EXPIRED:
181dab3f910Sjsing 	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
182dab3f910Sjsing 		BIO_printf(bio_err, "notAfter=");
1838e101a2aSdoug 		if (err_cert == NULL)
1848e101a2aSdoug 			BIO_printf(bio_err, " <error getting cert>");
1858e101a2aSdoug 		else
186dab3f910Sjsing 			ASN1_TIME_print(bio_err, X509_get_notAfter(err_cert));
187dab3f910Sjsing 		BIO_printf(bio_err, "\n");
188dab3f910Sjsing 		break;
189dab3f910Sjsing 	case X509_V_ERR_NO_EXPLICIT_POLICY:
190dab3f910Sjsing 		break;
191dab3f910Sjsing 	}
192dab3f910Sjsing 
193dab3f910Sjsing 	BIO_printf(bio_err, "verify return:%d\n", ok);
194dab3f910Sjsing 	return (ok);
195dab3f910Sjsing }
196dab3f910Sjsing 
197dab3f910Sjsing int
198dab3f910Sjsing set_cert_stuff(SSL_CTX * ctx, char *cert_file, char *key_file)
199dab3f910Sjsing {
200e7c1cbcdStb 	if (cert_file == NULL)
201e7c1cbcdStb 		return 1;
202e7c1cbcdStb 
203e7c1cbcdStb 	if (key_file == NULL)
204e7c1cbcdStb 		key_file = cert_file;
205e7c1cbcdStb 
206e7c1cbcdStb 	if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) {
207dab3f910Sjsing 		BIO_printf(bio_err,
208dab3f910Sjsing 		    "unable to get certificate from '%s'\n", cert_file);
209dab3f910Sjsing 		ERR_print_errors(bio_err);
210e7c1cbcdStb 		return 0;
211dab3f910Sjsing 	}
212e7c1cbcdStb 	if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) {
213e7c1cbcdStb 		BIO_printf(bio_err, "unable to get private key from '%s'\n",
214e7c1cbcdStb 		    key_file);
215dab3f910Sjsing 		ERR_print_errors(bio_err);
216e7c1cbcdStb 		return 0;
217dab3f910Sjsing 	}
218dab3f910Sjsing 
219e7c1cbcdStb 	/* Now we know that a key and cert have been set against the context. */
220dab3f910Sjsing 	if (!SSL_CTX_check_private_key(ctx)) {
221dab3f910Sjsing 		BIO_printf(bio_err,
222dab3f910Sjsing 		    "Private key does not match the certificate public key\n");
223e7c1cbcdStb 		return 0;
224dab3f910Sjsing 	}
225e7c1cbcdStb 
226e7c1cbcdStb 	return 1;
227dab3f910Sjsing }
228dab3f910Sjsing 
229dab3f910Sjsing int
230dab3f910Sjsing set_cert_key_stuff(SSL_CTX * ctx, X509 * cert, EVP_PKEY * key)
231dab3f910Sjsing {
232dab3f910Sjsing 	if (cert == NULL)
233dab3f910Sjsing 		return 1;
234dab3f910Sjsing 	if (SSL_CTX_use_certificate(ctx, cert) <= 0) {
235dab3f910Sjsing 		BIO_printf(bio_err, "error setting certificate\n");
236dab3f910Sjsing 		ERR_print_errors(bio_err);
237dab3f910Sjsing 		return 0;
238dab3f910Sjsing 	}
239dab3f910Sjsing 	if (SSL_CTX_use_PrivateKey(ctx, key) <= 0) {
240dab3f910Sjsing 		BIO_printf(bio_err, "error setting private key\n");
241dab3f910Sjsing 		ERR_print_errors(bio_err);
242dab3f910Sjsing 		return 0;
243dab3f910Sjsing 	}
244dab3f910Sjsing 	/*
245dab3f910Sjsing 	 * Now we know that a key and cert have been set against the SSL
246dab3f910Sjsing 	 * context
247dab3f910Sjsing 	 */
248dab3f910Sjsing 	if (!SSL_CTX_check_private_key(ctx)) {
249dab3f910Sjsing 		BIO_printf(bio_err,
250dab3f910Sjsing 		    "Private key does not match the certificate public key\n");
251dab3f910Sjsing 		return 0;
252dab3f910Sjsing 	}
253dab3f910Sjsing 	return 1;
254dab3f910Sjsing }
255dab3f910Sjsing 
25657a9ba28Sjsing int
25757a9ba28Sjsing ssl_print_tmp_key(BIO *out, SSL *s)
25857a9ba28Sjsing {
25957a9ba28Sjsing 	const char *cname;
26057a9ba28Sjsing 	EVP_PKEY *pkey;
26157a9ba28Sjsing 	EC_KEY *ec;
262709513a4Stb 	const EC_GROUP *group;
26357a9ba28Sjsing 	int nid;
26457a9ba28Sjsing 
26557a9ba28Sjsing 	if (!SSL_get_server_tmp_key(s, &pkey))
26657a9ba28Sjsing 		return 0;
26757a9ba28Sjsing 
26857a9ba28Sjsing 	BIO_puts(out, "Server Temp Key: ");
26957a9ba28Sjsing 	switch (EVP_PKEY_id(pkey)) {
27057a9ba28Sjsing 	case EVP_PKEY_DH:
27157a9ba28Sjsing 		BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(pkey));
27257a9ba28Sjsing 		break;
27357a9ba28Sjsing 
27457a9ba28Sjsing 	case EVP_PKEY_EC:
275709513a4Stb 		if ((ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL)
276709513a4Stb 			goto err;
277709513a4Stb 		if ((group = EC_KEY_get0_group(ec)) == NULL)
278709513a4Stb 			goto err;
279709513a4Stb 
280709513a4Stb 		nid = EC_GROUP_get_curve_name(group);
28157a9ba28Sjsing 
28257a9ba28Sjsing 		if ((cname = EC_curve_nid2nist(nid)) == NULL)
28357a9ba28Sjsing 			cname = OBJ_nid2sn(nid);
28457a9ba28Sjsing 
28557a9ba28Sjsing 		BIO_printf(out, "ECDH, %s, %d bits\n", cname, EVP_PKEY_bits(pkey));
28657a9ba28Sjsing 		break;
28757a9ba28Sjsing 
28857a9ba28Sjsing 	default:
28957a9ba28Sjsing 		BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_id(pkey)),
29057a9ba28Sjsing 		    EVP_PKEY_bits(pkey));
29157a9ba28Sjsing 	}
29257a9ba28Sjsing 
293709513a4Stb  err:
29457a9ba28Sjsing 	EVP_PKEY_free(pkey);
29557a9ba28Sjsing 	return 1;
29657a9ba28Sjsing }
29757a9ba28Sjsing 
298dab3f910Sjsing long
299dab3f910Sjsing bio_dump_callback(BIO * bio, int cmd, const char *argp,
300dab3f910Sjsing     int argi, long argl, long ret)
301dab3f910Sjsing {
302dab3f910Sjsing 	BIO *out;
303dab3f910Sjsing 
304dab3f910Sjsing 	out = (BIO *) BIO_get_callback_arg(bio);
305dab3f910Sjsing 	if (out == NULL)
306dab3f910Sjsing 		return (ret);
307dab3f910Sjsing 
308dab3f910Sjsing 	if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
309dab3f910Sjsing 		BIO_printf(out,
310dab3f910Sjsing 		    "read from %p [%p] (%lu bytes => %ld (0x%lX))\n",
311dab3f910Sjsing 		    (void *) bio, argp, (unsigned long) argi, ret, ret);
312dab3f910Sjsing 		BIO_dump(out, argp, (int) ret);
313dab3f910Sjsing 		return (ret);
314dab3f910Sjsing 	} else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
315dab3f910Sjsing 		BIO_printf(out,
316dab3f910Sjsing 		    "write to %p [%p] (%lu bytes => %ld (0x%lX))\n",
317dab3f910Sjsing 		    (void *) bio, argp, (unsigned long) argi, ret, ret);
318dab3f910Sjsing 		BIO_dump(out, argp, (int) ret);
319dab3f910Sjsing 	}
320dab3f910Sjsing 	return (ret);
321dab3f910Sjsing }
322dab3f910Sjsing 
323dab3f910Sjsing void
324dab3f910Sjsing apps_ssl_info_callback(const SSL * s, int where, int ret)
325dab3f910Sjsing {
326dab3f910Sjsing 	const char *str;
327dab3f910Sjsing 	int w;
328dab3f910Sjsing 
329dab3f910Sjsing 	w = where & ~SSL_ST_MASK;
330dab3f910Sjsing 
331dab3f910Sjsing 	if (w & SSL_ST_CONNECT)
332dab3f910Sjsing 		str = "SSL_connect";
333dab3f910Sjsing 	else if (w & SSL_ST_ACCEPT)
334dab3f910Sjsing 		str = "SSL_accept";
335dab3f910Sjsing 	else
336dab3f910Sjsing 		str = "undefined";
337dab3f910Sjsing 
338dab3f910Sjsing 	if (where & SSL_CB_LOOP) {
339dab3f910Sjsing 		BIO_printf(bio_err, "%s:%s\n", str, SSL_state_string_long(s));
340dab3f910Sjsing 	} else if (where & SSL_CB_ALERT) {
341dab3f910Sjsing 		str = (where & SSL_CB_READ) ? "read" : "write";
342dab3f910Sjsing 		BIO_printf(bio_err, "SSL3 alert %s:%s:%s\n", str,
343dab3f910Sjsing 		    SSL_alert_type_string_long(ret),
344dab3f910Sjsing 		    SSL_alert_desc_string_long(ret));
345dab3f910Sjsing 	} else if (where & SSL_CB_EXIT) {
346dab3f910Sjsing 		if (ret == 0)
347dab3f910Sjsing 			BIO_printf(bio_err, "%s:failed in %s\n",
348dab3f910Sjsing 			    str, SSL_state_string_long(s));
349dab3f910Sjsing 		else if (ret < 0) {
350dab3f910Sjsing 			BIO_printf(bio_err, "%s:error in %s\n",
351dab3f910Sjsing 			    str, SSL_state_string_long(s));
352dab3f910Sjsing 		}
353dab3f910Sjsing 	}
354dab3f910Sjsing }
355dab3f910Sjsing 
356dab3f910Sjsing 
357dab3f910Sjsing void
358dab3f910Sjsing msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL * ssl, void *arg)
359dab3f910Sjsing {
360dab3f910Sjsing 	BIO *bio = arg;
361dab3f910Sjsing 	const char *str_write_p, *str_version, *str_content_type = "",
362dab3f910Sjsing 	    *str_details1 = "", *str_details2 = "";
363dab3f910Sjsing 
364dab3f910Sjsing 	str_write_p = write_p ? ">>>" : "<<<";
365dab3f910Sjsing 
36688411e53Stb 	/* XXX convert to using ssl_get_version */
367dab3f910Sjsing 	switch (version) {
368dab3f910Sjsing 	case SSL2_VERSION:
369dab3f910Sjsing 		str_version = "SSL 2.0";
370dab3f910Sjsing 		break;
371dab3f910Sjsing 	case SSL3_VERSION:
372dab3f910Sjsing 		str_version = "SSL 3.0 ";
373dab3f910Sjsing 		break;
374dab3f910Sjsing 	case TLS1_VERSION:
375dab3f910Sjsing 		str_version = "TLS 1.0 ";
376dab3f910Sjsing 		break;
377dab3f910Sjsing 	case TLS1_1_VERSION:
378dab3f910Sjsing 		str_version = "TLS 1.1 ";
379dab3f910Sjsing 		break;
380dab3f910Sjsing 	case TLS1_2_VERSION:
381dab3f910Sjsing 		str_version = "TLS 1.2 ";
382dab3f910Sjsing 		break;
383654e66e6Stb 	case TLS1_3_VERSION:
384654e66e6Stb 		str_version = "TLS 1.3 ";
385654e66e6Stb 		break;
386dab3f910Sjsing 	case DTLS1_VERSION:
387dab3f910Sjsing 		str_version = "DTLS 1.0 ";
388dab3f910Sjsing 		break;
389e8cca36cSinoguchi 	case DTLS1_2_VERSION:
390e8cca36cSinoguchi 		str_version = "DTLS 1.2 ";
391e8cca36cSinoguchi 		break;
392dab3f910Sjsing 	default:
393dab3f910Sjsing 		str_version = "???";
394dab3f910Sjsing 	}
395dab3f910Sjsing 
396dab3f910Sjsing 	if (version == SSL2_VERSION) {
397dab3f910Sjsing 		str_details1 = "???";
398dab3f910Sjsing 
399dab3f910Sjsing 		if (len > 0) {
40088411e53Stb 			/* XXX magic numbers */
401dab3f910Sjsing 			switch (((const unsigned char *) buf)[0]) {
402dab3f910Sjsing 			case 0:
403dab3f910Sjsing 				str_details1 = ", ERROR:";
404dab3f910Sjsing 				str_details2 = " ???";
405dab3f910Sjsing 				if (len >= 3) {
406dab3f910Sjsing 					unsigned err = (((const unsigned char *) buf)[1] << 8) + ((const unsigned char *) buf)[2];
407dab3f910Sjsing 
408dab3f910Sjsing 					switch (err) {
409dab3f910Sjsing 					case 0x0001:
410dab3f910Sjsing 						str_details2 = " NO-CIPHER-ERROR";
411dab3f910Sjsing 						break;
412dab3f910Sjsing 					case 0x0002:
413dab3f910Sjsing 						str_details2 = " NO-CERTIFICATE-ERROR";
414dab3f910Sjsing 						break;
415dab3f910Sjsing 					case 0x0004:
416dab3f910Sjsing 						str_details2 = " BAD-CERTIFICATE-ERROR";
417dab3f910Sjsing 						break;
418dab3f910Sjsing 					case 0x0006:
419dab3f910Sjsing 						str_details2 = " UNSUPPORTED-CERTIFICATE-TYPE-ERROR";
420dab3f910Sjsing 						break;
421dab3f910Sjsing 					}
422dab3f910Sjsing 				}
423dab3f910Sjsing 				break;
424dab3f910Sjsing 			case 1:
425dab3f910Sjsing 				str_details1 = ", CLIENT-HELLO";
426dab3f910Sjsing 				break;
427dab3f910Sjsing 			case 2:
428dab3f910Sjsing 				str_details1 = ", CLIENT-MASTER-KEY";
429dab3f910Sjsing 				break;
430dab3f910Sjsing 			case 3:
431dab3f910Sjsing 				str_details1 = ", CLIENT-FINISHED";
432dab3f910Sjsing 				break;
433dab3f910Sjsing 			case 4:
434dab3f910Sjsing 				str_details1 = ", SERVER-HELLO";
435dab3f910Sjsing 				break;
436dab3f910Sjsing 			case 5:
437dab3f910Sjsing 				str_details1 = ", SERVER-VERIFY";
438dab3f910Sjsing 				break;
439dab3f910Sjsing 			case 6:
440dab3f910Sjsing 				str_details1 = ", SERVER-FINISHED";
441dab3f910Sjsing 				break;
442dab3f910Sjsing 			case 7:
443dab3f910Sjsing 				str_details1 = ", REQUEST-CERTIFICATE";
444dab3f910Sjsing 				break;
445dab3f910Sjsing 			case 8:
446dab3f910Sjsing 				str_details1 = ", CLIENT-CERTIFICATE";
447dab3f910Sjsing 				break;
448dab3f910Sjsing 			}
449dab3f910Sjsing 		}
450dab3f910Sjsing 	}
451dab3f910Sjsing 	if (version == SSL3_VERSION || version == TLS1_VERSION ||
452dab3f910Sjsing 	    version == TLS1_1_VERSION || version == TLS1_2_VERSION ||
453e8cca36cSinoguchi 	    version == TLS1_3_VERSION || version == DTLS1_VERSION ||
454e8cca36cSinoguchi 	    version == DTLS1_2_VERSION) {
45588411e53Stb 		/* XXX magic numbers are in ssl3.h */
456dab3f910Sjsing 		switch (content_type) {
457dab3f910Sjsing 		case 20:
458dab3f910Sjsing 			str_content_type = "ChangeCipherSpec";
459dab3f910Sjsing 			break;
460dab3f910Sjsing 		case 21:
461dab3f910Sjsing 			str_content_type = "Alert";
462dab3f910Sjsing 			break;
463dab3f910Sjsing 		case 22:
464dab3f910Sjsing 			str_content_type = "Handshake";
465dab3f910Sjsing 			break;
466dab3f910Sjsing 		}
467dab3f910Sjsing 
468dab3f910Sjsing 		if (content_type == 21) {	/* Alert */
469dab3f910Sjsing 			str_details1 = ", ???";
470dab3f910Sjsing 
471dab3f910Sjsing 			if (len == 2) {
472dab3f910Sjsing 				switch (((const unsigned char *) buf)[0]) {
473dab3f910Sjsing 				case 1:
474dab3f910Sjsing 					str_details1 = ", warning";
475dab3f910Sjsing 					break;
476dab3f910Sjsing 				case 2:
477dab3f910Sjsing 					str_details1 = ", fatal";
478dab3f910Sjsing 					break;
479dab3f910Sjsing 				}
480dab3f910Sjsing 
481dab3f910Sjsing 				str_details2 = " ???";
482dab3f910Sjsing 				switch (((const unsigned char *) buf)[1]) {
483dab3f910Sjsing 				case 0:
484dab3f910Sjsing 					str_details2 = " close_notify";
485dab3f910Sjsing 					break;
486dab3f910Sjsing 				case 10:
487dab3f910Sjsing 					str_details2 = " unexpected_message";
488dab3f910Sjsing 					break;
489dab3f910Sjsing 				case 20:
490dab3f910Sjsing 					str_details2 = " bad_record_mac";
491dab3f910Sjsing 					break;
492dab3f910Sjsing 				case 21:
493dab3f910Sjsing 					str_details2 = " decryption_failed";
494dab3f910Sjsing 					break;
495dab3f910Sjsing 				case 22:
496dab3f910Sjsing 					str_details2 = " record_overflow";
497dab3f910Sjsing 					break;
498dab3f910Sjsing 				case 30:
499dab3f910Sjsing 					str_details2 = " decompression_failure";
500dab3f910Sjsing 					break;
501dab3f910Sjsing 				case 40:
502dab3f910Sjsing 					str_details2 = " handshake_failure";
503dab3f910Sjsing 					break;
504dab3f910Sjsing 				case 42:
505dab3f910Sjsing 					str_details2 = " bad_certificate";
506dab3f910Sjsing 					break;
507dab3f910Sjsing 				case 43:
508dab3f910Sjsing 					str_details2 = " unsupported_certificate";
509dab3f910Sjsing 					break;
510dab3f910Sjsing 				case 44:
511dab3f910Sjsing 					str_details2 = " certificate_revoked";
512dab3f910Sjsing 					break;
513dab3f910Sjsing 				case 45:
514dab3f910Sjsing 					str_details2 = " certificate_expired";
515dab3f910Sjsing 					break;
516dab3f910Sjsing 				case 46:
517dab3f910Sjsing 					str_details2 = " certificate_unknown";
518dab3f910Sjsing 					break;
519dab3f910Sjsing 				case 47:
520dab3f910Sjsing 					str_details2 = " illegal_parameter";
521dab3f910Sjsing 					break;
522dab3f910Sjsing 				case 48:
523dab3f910Sjsing 					str_details2 = " unknown_ca";
524dab3f910Sjsing 					break;
525dab3f910Sjsing 				case 49:
526dab3f910Sjsing 					str_details2 = " access_denied";
527dab3f910Sjsing 					break;
528dab3f910Sjsing 				case 50:
529dab3f910Sjsing 					str_details2 = " decode_error";
530dab3f910Sjsing 					break;
531dab3f910Sjsing 				case 51:
532dab3f910Sjsing 					str_details2 = " decrypt_error";
533dab3f910Sjsing 					break;
534dab3f910Sjsing 				case 60:
535dab3f910Sjsing 					str_details2 = " export_restriction";
536dab3f910Sjsing 					break;
537dab3f910Sjsing 				case 70:
538dab3f910Sjsing 					str_details2 = " protocol_version";
539dab3f910Sjsing 					break;
540dab3f910Sjsing 				case 71:
541dab3f910Sjsing 					str_details2 = " insufficient_security";
542dab3f910Sjsing 					break;
543dab3f910Sjsing 				case 80:
544dab3f910Sjsing 					str_details2 = " internal_error";
545dab3f910Sjsing 					break;
546dab3f910Sjsing 				case 90:
547dab3f910Sjsing 					str_details2 = " user_canceled";
548dab3f910Sjsing 					break;
549dab3f910Sjsing 				case 100:
550dab3f910Sjsing 					str_details2 = " no_renegotiation";
551dab3f910Sjsing 					break;
552dab3f910Sjsing 				case 110:
553dab3f910Sjsing 					str_details2 = " unsupported_extension";
554dab3f910Sjsing 					break;
555dab3f910Sjsing 				case 111:
556dab3f910Sjsing 					str_details2 = " certificate_unobtainable";
557dab3f910Sjsing 					break;
558dab3f910Sjsing 				case 112:
559dab3f910Sjsing 					str_details2 = " unrecognized_name";
560dab3f910Sjsing 					break;
561dab3f910Sjsing 				case 113:
562dab3f910Sjsing 					str_details2 = " bad_certificate_status_response";
563dab3f910Sjsing 					break;
564dab3f910Sjsing 				case 114:
565dab3f910Sjsing 					str_details2 = " bad_certificate_hash_value";
566dab3f910Sjsing 					break;
567dab3f910Sjsing 				case 115:
568dab3f910Sjsing 					str_details2 = " unknown_psk_identity";
569dab3f910Sjsing 					break;
570dab3f910Sjsing 				}
571dab3f910Sjsing 			}
572dab3f910Sjsing 		}
573dab3f910Sjsing 		if (content_type == 22) {	/* Handshake */
574dab3f910Sjsing 			str_details1 = "???";
575dab3f910Sjsing 
576dab3f910Sjsing 			if (len > 0) {
577dab3f910Sjsing 				switch (((const unsigned char *) buf)[0]) {
578dab3f910Sjsing 				case 0:
579dab3f910Sjsing 					str_details1 = ", HelloRequest";
580dab3f910Sjsing 					break;
581dab3f910Sjsing 				case 1:
582dab3f910Sjsing 					str_details1 = ", ClientHello";
583dab3f910Sjsing 					break;
584dab3f910Sjsing 				case 2:
585dab3f910Sjsing 					str_details1 = ", ServerHello";
586dab3f910Sjsing 					break;
587dab3f910Sjsing 				case 3:
588dab3f910Sjsing 					str_details1 = ", HelloVerifyRequest";
589dab3f910Sjsing 					break;
590654e66e6Stb 				case 4:
591654e66e6Stb 					str_details1 = ", NewSessionTicket";
592654e66e6Stb 					break;
593654e66e6Stb 				case 5:
594654e66e6Stb 					str_details1 = ", EndOfEarlyData";
595654e66e6Stb 					break;
596654e66e6Stb 				case 8:
597654e66e6Stb 					str_details1 = ", EncryptedExtensions";
598654e66e6Stb 					break;
599dab3f910Sjsing 				case 11:
600dab3f910Sjsing 					str_details1 = ", Certificate";
601dab3f910Sjsing 					break;
602dab3f910Sjsing 				case 12:
603dab3f910Sjsing 					str_details1 = ", ServerKeyExchange";
604dab3f910Sjsing 					break;
605dab3f910Sjsing 				case 13:
606dab3f910Sjsing 					str_details1 = ", CertificateRequest";
607dab3f910Sjsing 					break;
608dab3f910Sjsing 				case 14:
609dab3f910Sjsing 					str_details1 = ", ServerHelloDone";
610dab3f910Sjsing 					break;
611dab3f910Sjsing 				case 15:
612dab3f910Sjsing 					str_details1 = ", CertificateVerify";
613dab3f910Sjsing 					break;
614dab3f910Sjsing 				case 16:
615dab3f910Sjsing 					str_details1 = ", ClientKeyExchange";
616dab3f910Sjsing 					break;
617dab3f910Sjsing 				case 20:
618dab3f910Sjsing 					str_details1 = ", Finished";
619dab3f910Sjsing 					break;
620654e66e6Stb 				case 24:
621654e66e6Stb 					str_details1 = ", KeyUpdate";
622654e66e6Stb 					break;
623dab3f910Sjsing 				}
624dab3f910Sjsing 			}
625dab3f910Sjsing 		}
626dab3f910Sjsing 	}
627dab3f910Sjsing 	BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p,
628dab3f910Sjsing 	    str_version, str_content_type, (unsigned long) len,
629dab3f910Sjsing 	    str_details1, str_details2);
630dab3f910Sjsing 
631dab3f910Sjsing 	if (len > 0) {
632dab3f910Sjsing 		size_t num, i;
633dab3f910Sjsing 
634dab3f910Sjsing 		BIO_printf(bio, "   ");
635dab3f910Sjsing 		num = len;
636275363c2Sdoug 
637dab3f910Sjsing 		for (i = 0; i < num; i++) {
638dab3f910Sjsing 			if (i % 16 == 0 && i > 0)
639dab3f910Sjsing 				BIO_printf(bio, "\n   ");
640dab3f910Sjsing 			BIO_printf(bio, " %02x",
641dab3f910Sjsing 			    ((const unsigned char *) buf)[i]);
642dab3f910Sjsing 		}
643dab3f910Sjsing 		if (i < len)
644dab3f910Sjsing 			BIO_printf(bio, " ...");
645dab3f910Sjsing 		BIO_printf(bio, "\n");
646dab3f910Sjsing 	}
647dab3f910Sjsing 	(void) BIO_flush(bio);
648dab3f910Sjsing }
649dab3f910Sjsing 
650dab3f910Sjsing void
651dab3f910Sjsing tlsext_cb(SSL * s, int client_server, int type, unsigned char *data, int len,
652dab3f910Sjsing     void *arg)
653dab3f910Sjsing {
654dab3f910Sjsing 	BIO *bio = arg;
655dab3f910Sjsing 	char *extname;
656dab3f910Sjsing 
657dab3f910Sjsing 	switch (type) {
658dab3f910Sjsing 	case TLSEXT_TYPE_server_name:
659dab3f910Sjsing 		extname = "server name";
660dab3f910Sjsing 		break;
661dab3f910Sjsing 
662dab3f910Sjsing 	case TLSEXT_TYPE_max_fragment_length:
663dab3f910Sjsing 		extname = "max fragment length";
664dab3f910Sjsing 		break;
665dab3f910Sjsing 
666dab3f910Sjsing 	case TLSEXT_TYPE_client_certificate_url:
667dab3f910Sjsing 		extname = "client certificate URL";
668dab3f910Sjsing 		break;
669dab3f910Sjsing 
670dab3f910Sjsing 	case TLSEXT_TYPE_trusted_ca_keys:
671dab3f910Sjsing 		extname = "trusted CA keys";
672dab3f910Sjsing 		break;
673dab3f910Sjsing 
674dab3f910Sjsing 	case TLSEXT_TYPE_truncated_hmac:
675dab3f910Sjsing 		extname = "truncated HMAC";
676dab3f910Sjsing 		break;
677dab3f910Sjsing 
678dab3f910Sjsing 	case TLSEXT_TYPE_status_request:
679dab3f910Sjsing 		extname = "status request";
680dab3f910Sjsing 		break;
681dab3f910Sjsing 
682dab3f910Sjsing 	case TLSEXT_TYPE_user_mapping:
683dab3f910Sjsing 		extname = "user mapping";
684dab3f910Sjsing 		break;
685dab3f910Sjsing 
686dab3f910Sjsing 	case TLSEXT_TYPE_client_authz:
687dab3f910Sjsing 		extname = "client authz";
688dab3f910Sjsing 		break;
689dab3f910Sjsing 
690dab3f910Sjsing 	case TLSEXT_TYPE_server_authz:
691dab3f910Sjsing 		extname = "server authz";
692dab3f910Sjsing 		break;
693dab3f910Sjsing 
694dab3f910Sjsing 	case TLSEXT_TYPE_cert_type:
695dab3f910Sjsing 		extname = "cert type";
696dab3f910Sjsing 		break;
697dab3f910Sjsing 
69860717e0aSjsing 	case TLSEXT_TYPE_supported_groups:
69960717e0aSjsing 		extname = "supported groups";
700dab3f910Sjsing 		break;
701dab3f910Sjsing 
702dab3f910Sjsing 	case TLSEXT_TYPE_ec_point_formats:
703dab3f910Sjsing 		extname = "EC point formats";
704dab3f910Sjsing 		break;
705dab3f910Sjsing 
706dab3f910Sjsing 	case TLSEXT_TYPE_srp:
707dab3f910Sjsing 		extname = "SRP";
708dab3f910Sjsing 		break;
709dab3f910Sjsing 
710dab3f910Sjsing 	case TLSEXT_TYPE_signature_algorithms:
711dab3f910Sjsing 		extname = "signature algorithms";
712dab3f910Sjsing 		break;
713dab3f910Sjsing 
714dab3f910Sjsing 	case TLSEXT_TYPE_use_srtp:
715dab3f910Sjsing 		extname = "use SRTP";
716dab3f910Sjsing 		break;
717dab3f910Sjsing 
718dab3f910Sjsing 	case TLSEXT_TYPE_heartbeat:
719dab3f910Sjsing 		extname = "heartbeat";
720dab3f910Sjsing 		break;
721dab3f910Sjsing 
722afd7a2e1Sinoguchi 	case TLSEXT_TYPE_application_layer_protocol_negotiation:
723afd7a2e1Sinoguchi 		extname = "application layer protocol negotiation";
724afd7a2e1Sinoguchi 		break;
725afd7a2e1Sinoguchi 
726afd7a2e1Sinoguchi 	case TLSEXT_TYPE_padding:
727afd7a2e1Sinoguchi 		extname = "TLS padding";
728afd7a2e1Sinoguchi 		break;
729afd7a2e1Sinoguchi 
730e14d36e1Sinoguchi 	case TLSEXT_TYPE_session_ticket:
731e14d36e1Sinoguchi 		extname = "session ticket";
732e14d36e1Sinoguchi 		break;
733e14d36e1Sinoguchi 
734e14d36e1Sinoguchi #if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL)
735e14d36e1Sinoguchi 	case TLSEXT_TYPE_pre_shared_key:
736e14d36e1Sinoguchi 		extname = "pre shared key";
737e14d36e1Sinoguchi 		break;
738e14d36e1Sinoguchi 
739e14d36e1Sinoguchi 	case TLSEXT_TYPE_early_data:
740e14d36e1Sinoguchi 		extname = "early data";
741e14d36e1Sinoguchi 		break;
742e14d36e1Sinoguchi 
743e14d36e1Sinoguchi 	case TLSEXT_TYPE_supported_versions:
744e14d36e1Sinoguchi 		extname = "supported versions";
745e14d36e1Sinoguchi 		break;
746e14d36e1Sinoguchi 
747e14d36e1Sinoguchi 	case TLSEXT_TYPE_cookie:
748e14d36e1Sinoguchi 		extname = "cookie";
749e14d36e1Sinoguchi 		break;
750e14d36e1Sinoguchi 
751e14d36e1Sinoguchi 	case TLSEXT_TYPE_psk_key_exchange_modes:
752e14d36e1Sinoguchi 		extname = "PSK key exchange modes";
753e14d36e1Sinoguchi 		break;
754e14d36e1Sinoguchi 
755e14d36e1Sinoguchi 	case TLSEXT_TYPE_certificate_authorities:
756e14d36e1Sinoguchi 		extname = "certificate authorities";
757e14d36e1Sinoguchi 		break;
758e14d36e1Sinoguchi 
759e14d36e1Sinoguchi 	case TLSEXT_TYPE_oid_filters:
760e14d36e1Sinoguchi 		extname = "OID filters";
761e14d36e1Sinoguchi 		break;
762e14d36e1Sinoguchi 
763e14d36e1Sinoguchi 	case TLSEXT_TYPE_post_handshake_auth:
764e14d36e1Sinoguchi 		extname = "post handshake auth";
765e14d36e1Sinoguchi 		break;
766e14d36e1Sinoguchi 
767e14d36e1Sinoguchi 	case TLSEXT_TYPE_signature_algorithms_cert:
768e14d36e1Sinoguchi 		extname = "signature algorithms cert";
769e14d36e1Sinoguchi 		break;
770e14d36e1Sinoguchi 
771e14d36e1Sinoguchi 	case TLSEXT_TYPE_key_share:
772e14d36e1Sinoguchi 		extname = "key share";
773e14d36e1Sinoguchi 		break;
774e14d36e1Sinoguchi #endif
775e14d36e1Sinoguchi 
776e14d36e1Sinoguchi 	case TLSEXT_TYPE_renegotiate:
777e14d36e1Sinoguchi 		extname = "renegotiation info";
778e14d36e1Sinoguchi 		break;
779e14d36e1Sinoguchi 
780dab3f910Sjsing 	default:
781dab3f910Sjsing 		extname = "unknown";
782dab3f910Sjsing 		break;
783dab3f910Sjsing 
784dab3f910Sjsing 	}
785dab3f910Sjsing 
786dab3f910Sjsing 	BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n",
787dab3f910Sjsing 	    client_server ? "server" : "client", extname, type, len);
788dab3f910Sjsing 	BIO_dump(bio, (char *) data, len);
789dab3f910Sjsing 	(void) BIO_flush(bio);
790dab3f910Sjsing }
791dab3f910Sjsing 
792dab3f910Sjsing int
793dab3f910Sjsing generate_cookie_callback(SSL * ssl, unsigned char *cookie,
794dab3f910Sjsing     unsigned int *cookie_len)
795dab3f910Sjsing {
796dab3f910Sjsing 	unsigned char *buffer, result[EVP_MAX_MD_SIZE];
797dab3f910Sjsing 	unsigned int length, resultlength;
798dab3f910Sjsing 	union {
799dab3f910Sjsing 		struct sockaddr sa;
800dab3f910Sjsing 		struct sockaddr_in s4;
801dab3f910Sjsing 		struct sockaddr_in6 s6;
802dab3f910Sjsing 	} peer;
803dab3f910Sjsing 
804dab3f910Sjsing 	/* Initialize a random secret */
805dab3f910Sjsing 	if (!cookie_initialized) {
806fd6ab616Sjsing 		arc4random_buf(cookie_secret, COOKIE_SECRET_LENGTH);
807dab3f910Sjsing 		cookie_initialized = 1;
808dab3f910Sjsing 	}
809dab3f910Sjsing 	/* Read peer information */
810dab3f910Sjsing 	(void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);
811dab3f910Sjsing 
812dab3f910Sjsing 	/* Create buffer with peer's address and port */
813dab3f910Sjsing 	length = 0;
814dab3f910Sjsing 	switch (peer.sa.sa_family) {
815dab3f910Sjsing 	case AF_INET:
816dab3f910Sjsing 		length += sizeof(struct in_addr);
817dab3f910Sjsing 		length += sizeof(peer.s4.sin_port);
818dab3f910Sjsing 		break;
819dab3f910Sjsing 	case AF_INET6:
820dab3f910Sjsing 		length += sizeof(struct in6_addr);
821dab3f910Sjsing 		length += sizeof(peer.s6.sin6_port);
822dab3f910Sjsing 		break;
823dab3f910Sjsing 	default:
824dab3f910Sjsing 		OPENSSL_assert(0);
825dab3f910Sjsing 		break;
826dab3f910Sjsing 	}
827dab3f910Sjsing 	buffer = malloc(length);
828dab3f910Sjsing 
829dab3f910Sjsing 	if (buffer == NULL) {
830dab3f910Sjsing 		BIO_printf(bio_err, "out of memory\n");
831dab3f910Sjsing 		return 0;
832dab3f910Sjsing 	}
833dab3f910Sjsing 	switch (peer.sa.sa_family) {
834dab3f910Sjsing 	case AF_INET:
835dab3f910Sjsing 		memcpy(buffer, &peer.s4.sin_port, sizeof(peer.s4.sin_port));
836dab3f910Sjsing 		memcpy(buffer + sizeof(peer.s4.sin_port),
837dab3f910Sjsing 		    &peer.s4.sin_addr, sizeof(struct in_addr));
838dab3f910Sjsing 		break;
839dab3f910Sjsing 	case AF_INET6:
840dab3f910Sjsing 		memcpy(buffer, &peer.s6.sin6_port, sizeof(peer.s6.sin6_port));
841dab3f910Sjsing 		memcpy(buffer + sizeof(peer.s6.sin6_port),
842dab3f910Sjsing 		    &peer.s6.sin6_addr, sizeof(struct in6_addr));
843dab3f910Sjsing 		break;
844dab3f910Sjsing 	default:
845dab3f910Sjsing 		OPENSSL_assert(0);
846dab3f910Sjsing 		break;
847dab3f910Sjsing 	}
848dab3f910Sjsing 
849dab3f910Sjsing 	/* Calculate HMAC of buffer using the secret */
850dab3f910Sjsing 	HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH,
851dab3f910Sjsing 	    buffer, length, result, &resultlength);
852dab3f910Sjsing 	free(buffer);
853dab3f910Sjsing 
854dab3f910Sjsing 	memcpy(cookie, result, resultlength);
855dab3f910Sjsing 	*cookie_len = resultlength;
856dab3f910Sjsing 
857dab3f910Sjsing 	return 1;
858dab3f910Sjsing }
859dab3f910Sjsing 
860dab3f910Sjsing int
8611524e5e0Stb verify_cookie_callback(SSL * ssl, const unsigned char *cookie,
8621524e5e0Stb     unsigned int cookie_len)
863dab3f910Sjsing {
864dab3f910Sjsing 	unsigned char *buffer, result[EVP_MAX_MD_SIZE];
865dab3f910Sjsing 	unsigned int length, resultlength;
866dab3f910Sjsing 	union {
867dab3f910Sjsing 		struct sockaddr sa;
868dab3f910Sjsing 		struct sockaddr_in s4;
869dab3f910Sjsing 		struct sockaddr_in6 s6;
870dab3f910Sjsing 	} peer;
871dab3f910Sjsing 
872dab3f910Sjsing 	/* If secret isn't initialized yet, the cookie can't be valid */
873dab3f910Sjsing 	if (!cookie_initialized)
874dab3f910Sjsing 		return 0;
875dab3f910Sjsing 
876dab3f910Sjsing 	/* Read peer information */
877dab3f910Sjsing 	(void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);
878dab3f910Sjsing 
879dab3f910Sjsing 	/* Create buffer with peer's address and port */
880dab3f910Sjsing 	length = 0;
881dab3f910Sjsing 	switch (peer.sa.sa_family) {
882dab3f910Sjsing 	case AF_INET:
883dab3f910Sjsing 		length += sizeof(struct in_addr);
884dab3f910Sjsing 		length += sizeof(peer.s4.sin_port);
885dab3f910Sjsing 		break;
886dab3f910Sjsing 	case AF_INET6:
887dab3f910Sjsing 		length += sizeof(struct in6_addr);
888dab3f910Sjsing 		length += sizeof(peer.s6.sin6_port);
889dab3f910Sjsing 		break;
890dab3f910Sjsing 	default:
891dab3f910Sjsing 		OPENSSL_assert(0);
892dab3f910Sjsing 		break;
893dab3f910Sjsing 	}
894dab3f910Sjsing 	buffer = malloc(length);
895dab3f910Sjsing 
896dab3f910Sjsing 	if (buffer == NULL) {
897dab3f910Sjsing 		BIO_printf(bio_err, "out of memory\n");
898dab3f910Sjsing 		return 0;
899dab3f910Sjsing 	}
900dab3f910Sjsing 	switch (peer.sa.sa_family) {
901dab3f910Sjsing 	case AF_INET:
902dab3f910Sjsing 		memcpy(buffer, &peer.s4.sin_port, sizeof(peer.s4.sin_port));
903dab3f910Sjsing 		memcpy(buffer + sizeof(peer.s4.sin_port),
904dab3f910Sjsing 		    &peer.s4.sin_addr, sizeof(struct in_addr));
905dab3f910Sjsing 		break;
906dab3f910Sjsing 	case AF_INET6:
907dab3f910Sjsing 		memcpy(buffer, &peer.s6.sin6_port, sizeof(peer.s6.sin6_port));
908dab3f910Sjsing 		memcpy(buffer + sizeof(peer.s6.sin6_port),
909dab3f910Sjsing 		    &peer.s6.sin6_addr, sizeof(struct in6_addr));
910dab3f910Sjsing 		break;
911dab3f910Sjsing 	default:
912dab3f910Sjsing 		OPENSSL_assert(0);
913dab3f910Sjsing 		break;
914dab3f910Sjsing 	}
915dab3f910Sjsing 
916dab3f910Sjsing 	/* Calculate HMAC of buffer using the secret */
9175aef4460Stb 	if (HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH,
9185aef4460Stb 	    buffer, length, result, &resultlength) == NULL) {
9195aef4460Stb 		free(buffer);
9205aef4460Stb 		return 0;
9215aef4460Stb 	}
9225aef4460Stb 
923dab3f910Sjsing 	free(buffer);
924dab3f910Sjsing 
925dab3f910Sjsing 	if (cookie_len == resultlength &&
926dab3f910Sjsing 	    memcmp(result, cookie, resultlength) == 0)
927dab3f910Sjsing 		return 1;
928dab3f910Sjsing 
929dab3f910Sjsing 	return 0;
930dab3f910Sjsing }
931