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