1 /* $OpenBSD: ciphers.c,v 1.13 2022/07/14 08:37:17 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 #include "progs.h" 26 27 struct { 28 int usage; 29 int use_supported; 30 int verbose; 31 } ciphers_config; 32 33 static const struct option ciphers_options[] = { 34 { 35 .name = "h", 36 .type = OPTION_FLAG, 37 .opt.flag = &ciphers_config.usage, 38 }, 39 { 40 .name = "?", 41 .type = OPTION_FLAG, 42 .opt.flag = &ciphers_config.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 = &ciphers_config.use_supported, 49 }, 50 { 51 .name = "tls1", 52 .type = OPTION_DISCARD, 53 }, 54 { 55 .name = "v", 56 .desc = "Provide cipher listing", 57 .type = OPTION_VALUE, 58 .opt.value = &ciphers_config.verbose, 59 .value = 1, 60 }, 61 { 62 .name = "V", 63 .desc = "Provide cipher listing with cipher suite values", 64 .type = OPTION_VALUE, 65 .opt.value = &ciphers_config.verbose, 66 .value = 2, 67 }, 68 { NULL }, 69 }; 70 71 static void 72 ciphers_usage(void) 73 { 74 fprintf(stderr, "usage: ciphers [-hsVv] [cipherlist]\n"); 75 options_usage(ciphers_options); 76 } 77 78 int 79 ciphers_main(int argc, char **argv) 80 { 81 char *cipherlist = NULL; 82 STACK_OF(SSL_CIPHER) *ciphers; 83 STACK_OF(SSL_CIPHER) *supported_ciphers = NULL; 84 const SSL_CIPHER *cipher; 85 SSL_CTX *ssl_ctx = NULL; 86 SSL *ssl = NULL; 87 uint16_t value; 88 int i, rv = 0; 89 char *desc; 90 91 if (single_execution) { 92 if (pledge("stdio rpath", NULL) == -1) { 93 perror("pledge"); 94 exit(1); 95 } 96 } 97 98 memset(&ciphers_config, 0, sizeof(ciphers_config)); 99 100 if (options_parse(argc, argv, ciphers_options, &cipherlist, 101 NULL) != 0) { 102 ciphers_usage(); 103 return (1); 104 } 105 106 if (ciphers_config.usage) { 107 ciphers_usage(); 108 return (1); 109 } 110 111 if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) 112 goto err; 113 114 if (cipherlist != NULL) { 115 if (SSL_CTX_set_cipher_list(ssl_ctx, cipherlist) == 0) 116 goto err; 117 } 118 119 if ((ssl = SSL_new(ssl_ctx)) == NULL) 120 goto err; 121 122 if (ciphers_config.use_supported) { 123 if ((supported_ciphers = 124 SSL_get1_supported_ciphers(ssl)) == NULL) 125 goto err; 126 ciphers = supported_ciphers; 127 } else { 128 if ((ciphers = SSL_get_ciphers(ssl)) == NULL) 129 goto err; 130 } 131 132 for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { 133 cipher = sk_SSL_CIPHER_value(ciphers, i); 134 if (ciphers_config.verbose == 0) { 135 fprintf(stdout, "%s%s", (i ? ":" : ""), 136 SSL_CIPHER_get_name(cipher)); 137 continue; 138 } 139 if (ciphers_config.verbose > 1) { 140 value = SSL_CIPHER_get_value(cipher); 141 fprintf(stdout, "%-*s0x%02X,0x%02X - ", 10, "", 142 ((value >> 8) & 0xff), (value & 0xff)); 143 } 144 desc = SSL_CIPHER_description(cipher, NULL, 0); 145 if (strcmp(desc, "OPENSSL_malloc Error") == 0) { 146 fprintf(stderr, "out of memory\n"); 147 goto err; 148 } 149 fprintf(stdout, "%s", desc); 150 free(desc); 151 } 152 if (ciphers_config.verbose == 0) 153 fprintf(stdout, "\n"); 154 155 goto done; 156 157 err: 158 ERR_print_errors_fp(stderr); 159 rv = 1; 160 161 done: 162 sk_SSL_CIPHER_free(supported_ciphers); 163 SSL_CTX_free(ssl_ctx); 164 SSL_free(ssl); 165 166 return (rv); 167 } 168