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