xref: /openbsd-src/usr.bin/openssl/ciphers.c (revision b0100c001bd51e907fb99299d4d3a1255d0e4452)
1*b0100c00Stb /* $OpenBSD: ciphers.c,v 1.20 2025/01/02 12:31:44 tb Exp $ */
2ed7e81deSjsing /*
3ed7e81deSjsing  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4dab3f910Sjsing  *
5ed7e81deSjsing  * Permission to use, copy, modify, and distribute this software for any
6ed7e81deSjsing  * purpose with or without fee is hereby granted, provided that the above
7ed7e81deSjsing  * copyright notice and this permission notice appear in all copies.
8dab3f910Sjsing  *
9ed7e81deSjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10ed7e81deSjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11ed7e81deSjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12ed7e81deSjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13ed7e81deSjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14ed7e81deSjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15ed7e81deSjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16dab3f910Sjsing  */
17dab3f910Sjsing 
18dab3f910Sjsing #include <stdio.h>
19dab3f910Sjsing #include <stdlib.h>
20dab3f910Sjsing 
21dab3f910Sjsing #include <openssl/err.h>
22dab3f910Sjsing #include <openssl/ssl.h>
23dab3f910Sjsing 
24ed7e81deSjsing #include "apps.h"
25ed7e81deSjsing 
26efc7e65fStb static struct {
27ed7e81deSjsing 	int usage;
286763e1a6Stb 	int use_supported;
29ed7e81deSjsing 	int verbose;
30572c5cebStb 	int version;
31e7718adaStb } cfg;
32ed7e81deSjsing 
33ea149709Sguenther static const struct option ciphers_options[] = {
34ed7e81deSjsing 	{
35ed7e81deSjsing 		.name = "h",
36ed7e81deSjsing 		.type = OPTION_FLAG,
37e7718adaStb 		.opt.flag = &cfg.usage,
38ed7e81deSjsing 	},
39ed7e81deSjsing 	{
40ed7e81deSjsing 		.name = "?",
41ed7e81deSjsing 		.type = OPTION_FLAG,
42e7718adaStb 		.opt.flag = &cfg.usage,
43ed7e81deSjsing 	},
44ed7e81deSjsing 	{
456763e1a6Stb 		.name = "s",
466763e1a6Stb 		.desc = "Only list ciphers that are supported by the TLS method",
476763e1a6Stb 		.type = OPTION_FLAG,
48e7718adaStb 		.opt.flag = &cfg.use_supported,
496763e1a6Stb 	},
506763e1a6Stb 	{
51572c5cebStb 		.name = "tls1_2",
52572c5cebStb 		.desc = "Use TLS protocol version 1.2",
53572c5cebStb 		.type = OPTION_VALUE,
54e7718adaStb 		.opt.value = &cfg.version,
55572c5cebStb 		.value = TLS1_2_VERSION,
56572c5cebStb 	},
57572c5cebStb 	{
58572c5cebStb 		.name = "tls1_3",
59572c5cebStb 		.desc = "Use TLS protocol version 1.3",
60572c5cebStb 		.type = OPTION_VALUE,
61e7718adaStb 		.opt.value = &cfg.version,
62572c5cebStb 		.value = TLS1_3_VERSION,
63ed7e81deSjsing 	},
64ed7e81deSjsing 	{
65ed7e81deSjsing 		.name = "v",
66ed7e81deSjsing 		.desc = "Provide cipher listing",
67ed7e81deSjsing 		.type = OPTION_VALUE,
68e7718adaStb 		.opt.value = &cfg.verbose,
69ed7e81deSjsing 		.value = 1,
70ed7e81deSjsing 	},
71ed7e81deSjsing 	{
72ed7e81deSjsing 		.name = "V",
73ed7e81deSjsing 		.desc = "Provide cipher listing with cipher suite values",
74ed7e81deSjsing 		.type = OPTION_VALUE,
75e7718adaStb 		.opt.value = &cfg.verbose,
76ed7e81deSjsing 		.value = 2,
77ed7e81deSjsing 	},
7840c8aa99Sjsing 	{ NULL },
79dab3f910Sjsing };
80dab3f910Sjsing 
81ed7e81deSjsing static void
82ed7e81deSjsing ciphers_usage(void)
83ed7e81deSjsing {
845e6abc6fStb 	fprintf(stderr, "usage: ciphers [-hsVv] [-tls1_2] "
85572c5cebStb 	    "[-tls1_3] [cipherlist]\n");
86ed7e81deSjsing 	options_usage(ciphers_options);
87ed7e81deSjsing }
88dab3f910Sjsing 
89dab3f910Sjsing int
90dab3f910Sjsing ciphers_main(int argc, char **argv)
91dab3f910Sjsing {
92ed7e81deSjsing 	char *cipherlist = NULL;
93ed7e81deSjsing 	STACK_OF(SSL_CIPHER) *ciphers;
946763e1a6Stb 	STACK_OF(SSL_CIPHER) *supported_ciphers = NULL;
95ed7e81deSjsing 	const SSL_CIPHER *cipher;
96ed7e81deSjsing 	SSL_CTX *ssl_ctx = NULL;
97dab3f910Sjsing 	SSL *ssl = NULL;
98ed7e81deSjsing 	uint16_t value;
99ed7e81deSjsing 	int i, rv = 0;
100dab3f910Sjsing 	char *desc;
101dab3f910Sjsing 
102e370f0eeSdoug 	if (pledge("stdio rpath", NULL) == -1) {
1039bc487adSdoug 		perror("pledge");
104e370f0eeSdoug 		exit(1);
105e370f0eeSdoug 	}
1069bc487adSdoug 
107e7718adaStb 	memset(&cfg, 0, sizeof(cfg));
10840c8aa99Sjsing 
109ed7e81deSjsing 	if (options_parse(argc, argv, ciphers_options, &cipherlist,
110ed7e81deSjsing 	    NULL) != 0) {
111ed7e81deSjsing 		ciphers_usage();
112ed7e81deSjsing 		return (1);
113ed7e81deSjsing 	}
114dab3f910Sjsing 
115e7718adaStb 	if (cfg.usage) {
116ed7e81deSjsing 		ciphers_usage();
117ed7e81deSjsing 		return (1);
118ed7e81deSjsing 	}
119dab3f910Sjsing 
120572c5cebStb 	if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL)
121ed7e81deSjsing 		goto err;
122dab3f910Sjsing 
123e7718adaStb 	if (cfg.version != 0) {
124572c5cebStb 		if (!SSL_CTX_set_min_proto_version(ssl_ctx,
125e7718adaStb 		    cfg.version))
126572c5cebStb 			goto err;
127572c5cebStb 		if (!SSL_CTX_set_max_proto_version(ssl_ctx,
128e7718adaStb 		    cfg.version))
129572c5cebStb 			goto err;
130572c5cebStb 	}
131572c5cebStb 
132ed7e81deSjsing 	if (cipherlist != NULL) {
133ed7e81deSjsing 		if (SSL_CTX_set_cipher_list(ssl_ctx, cipherlist) == 0)
134ed7e81deSjsing 			goto err;
135dab3f910Sjsing 	}
136ed7e81deSjsing 
137ed7e81deSjsing 	if ((ssl = SSL_new(ssl_ctx)) == NULL)
138ed7e81deSjsing 		goto err;
139ed7e81deSjsing 
140e7718adaStb 	if (cfg.use_supported) {
1416763e1a6Stb 		if ((supported_ciphers =
1426763e1a6Stb 		    SSL_get1_supported_ciphers(ssl)) == NULL)
1436763e1a6Stb 			goto err;
1446763e1a6Stb 		ciphers = supported_ciphers;
1456763e1a6Stb 	} else {
146ed7e81deSjsing 		if ((ciphers = SSL_get_ciphers(ssl)) == NULL)
147ed7e81deSjsing 			goto err;
1486763e1a6Stb 	}
149ed7e81deSjsing 
150ed7e81deSjsing 	for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
151ed7e81deSjsing 		cipher = sk_SSL_CIPHER_value(ciphers, i);
152e7718adaStb 		if (cfg.verbose == 0) {
153ed7e81deSjsing 			fprintf(stdout, "%s%s", (i ? ":" : ""),
154ed7e81deSjsing 			    SSL_CIPHER_get_name(cipher));
155ed7e81deSjsing 			continue;
156ed7e81deSjsing 		}
157e7718adaStb 		if (cfg.verbose > 1) {
158ed7e81deSjsing 			value = SSL_CIPHER_get_value(cipher);
159f73e9946Sbcook 			fprintf(stdout, "%-*s0x%02X,0x%02X - ", 10, "",
160ed7e81deSjsing 			    ((value >> 8) & 0xff), (value & 0xff));
161ed7e81deSjsing 		}
162ed7e81deSjsing 		desc = SSL_CIPHER_description(cipher, NULL, 0);
163ed7e81deSjsing 		if (strcmp(desc, "OPENSSL_malloc Error") == 0) {
164ed7e81deSjsing 			fprintf(stderr, "out of memory\n");
165ed7e81deSjsing 			goto err;
166ed7e81deSjsing 		}
167ed7e81deSjsing 		fprintf(stdout, "%s", desc);
168dab3f910Sjsing 		free(desc);
169dab3f910Sjsing 	}
170e7718adaStb 	if (cfg.verbose == 0)
171ed7e81deSjsing 		fprintf(stdout, "\n");
172dab3f910Sjsing 
173ed7e81deSjsing 	goto done;
174ed7e81deSjsing 
175dab3f910Sjsing  err:
176ed7e81deSjsing 	ERR_print_errors_fp(stderr);
177ed7e81deSjsing 	rv = 1;
178dab3f910Sjsing 
179ed7e81deSjsing  done:
1806763e1a6Stb 	sk_SSL_CIPHER_free(supported_ciphers);
181ed7e81deSjsing 	SSL_CTX_free(ssl_ctx);
182dab3f910Sjsing 	SSL_free(ssl);
183dab3f910Sjsing 
184ed7e81deSjsing 	return (rv);
185dab3f910Sjsing }
186