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