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