1 /* $OpenBSD: cipher_list.c,v 1.14 2022/12/17 16:05:28 jsing Exp $ */ 2 /* 3 * Copyright (c) 2015 Doug Hogan <doug@openbsd.org> 4 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * Test TLS ssl bytes (aka cipher suites) to cipher list and back. 21 * 22 * TLSv1.0 - RFC 2246 section 7.4.1.2 (ClientHello struct) 23 * TLSv1.1 - RFC 4346 section 7.4.1.2 (ClientHello struct) 24 * TLSv1.2 - RFC 5246 section 7.4.1.2 (ClientHello struct) 25 * 26 * In all of these standards, the relevant structures are: 27 * 28 * uint8 CipherSuite[2]; 29 * 30 * struct { 31 * ... 32 * CipherSuite cipher_suites<2..2^16-2> 33 * ... 34 * } ClientHello; 35 */ 36 37 #include <openssl/ssl.h> 38 39 #include <stdio.h> 40 #include <string.h> 41 42 #include "ssl_local.h" 43 44 #include "tests.h" 45 46 static uint8_t cipher_bytes[] = { 47 0xcc, 0xa8, /* ECDHE-ECDSA-CHACHA20-POLY1305 */ 48 0xcc, 0xa9, /* ECDHE-RSA-CHACHA20-POLY1305 */ 49 0xcc, 0xaa, /* DHE-RSA-CHACHA20-POLY1305 */ 50 0x00, 0x9c, /* AES128-GCM-SHA256 */ 51 0x00, 0x3d, /* AES256-SHA256 */ 52 }; 53 54 static uint8_t cipher_bytes_seclevel3[] = { 55 0xcc, 0xa8, /* ECDHE-ECDSA-CHACHA20-POLY1305 */ 56 0xcc, 0xa9, /* ECDHE-RSA-CHACHA20-POLY1305 */ 57 0xcc, 0xaa, /* DHE-RSA-CHACHA20-POLY1305 */ 58 }; 59 60 static uint16_t cipher_values[] = { 61 0xcca8, /* ECDHE-ECDSA-CHACHA20-POLY1305 */ 62 0xcca9, /* ECDHE-RSA-CHACHA20-POLY1305 */ 63 0xccaa, /* DHE-RSA-CHACHA20-POLY1305 */ 64 0x009c, /* AES128-GCM-SHA256 */ 65 0x003d, /* AES256-SHA256 */ 66 }; 67 68 #define N_CIPHERS (sizeof(cipher_bytes) / 2) 69 70 static int 71 ssl_bytes_to_list_alloc(SSL *s, STACK_OF(SSL_CIPHER) **ciphers) 72 { 73 SSL_CIPHER *cipher; 74 uint16_t value; 75 CBS cbs; 76 int i; 77 78 CBS_init(&cbs, cipher_bytes, sizeof(cipher_bytes)); 79 80 *ciphers = ssl_bytes_to_cipher_list(s, &cbs); 81 CHECK(*ciphers != NULL); 82 CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS); 83 for (i = 0; i < sk_SSL_CIPHER_num(*ciphers); i++) { 84 cipher = sk_SSL_CIPHER_value(*ciphers, i); 85 CHECK(cipher != NULL); 86 value = SSL_CIPHER_get_value(cipher); 87 CHECK(value == cipher_values[i]); 88 } 89 90 return 1; 91 } 92 93 static int 94 ssl_list_to_bytes_scsv(SSL *s, STACK_OF(SSL_CIPHER) **ciphers, 95 const uint8_t *cb, size_t cb_len) 96 { 97 CBB cbb; 98 unsigned char *buf = NULL; 99 size_t buflen, outlen; 100 int ret = 0; 101 102 /* Space for cipher bytes, plus reneg SCSV and two spare bytes. */ 103 CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS); 104 buflen = cb_len + 2 + 2; 105 CHECK((buf = calloc(1, buflen)) != NULL); 106 107 /* Clear renegotiate so it adds SCSV */ 108 s->renegotiate = 0; 109 110 CHECK_GOTO(CBB_init_fixed(&cbb, buf, buflen)); 111 CHECK_GOTO(ssl_cipher_list_to_bytes(s, *ciphers, &cbb)); 112 CHECK_GOTO(CBB_finish(&cbb, NULL, &outlen)); 113 114 CHECK_GOTO(outlen > 0 && outlen == cb_len + 2); 115 CHECK_GOTO(memcmp(buf, cb, cb_len) == 0); 116 CHECK_GOTO(buf[buflen - 4] == 0x00 && buf[buflen - 3] == 0xff); 117 CHECK_GOTO(buf[buflen - 2] == 0x00 && buf[buflen - 1] == 0x00); 118 119 ret = 1; 120 121 err: 122 free(buf); 123 return ret; 124 } 125 126 static int 127 ssl_list_to_bytes_no_scsv(SSL *s, STACK_OF(SSL_CIPHER) **ciphers, 128 const uint8_t *cb, size_t cb_len) 129 { 130 CBB cbb; 131 unsigned char *buf = NULL; 132 size_t buflen, outlen; 133 int ret = 0; 134 135 /* Space for cipher bytes and two spare bytes */ 136 CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS); 137 buflen = cb_len + 2; 138 CHECK((buf = calloc(1, buflen)) != NULL); 139 buf[buflen - 2] = 0xfe; 140 buf[buflen - 1] = 0xab; 141 142 /* Set renegotiate so it doesn't add SCSV */ 143 s->renegotiate = 1; 144 145 CHECK_GOTO(CBB_init_fixed(&cbb, buf, buflen)); 146 CHECK_GOTO(ssl_cipher_list_to_bytes(s, *ciphers, &cbb)); 147 CHECK_GOTO(CBB_finish(&cbb, NULL, &outlen)); 148 149 CHECK_GOTO(outlen > 0 && outlen == cb_len); 150 CHECK_GOTO(memcmp(buf, cb, cb_len) == 0); 151 CHECK_GOTO(buf[buflen - 2] == 0xfe && buf[buflen - 1] == 0xab); 152 153 ret = 1; 154 155 err: 156 free(buf); 157 return ret; 158 } 159 160 static int 161 ssl_bytes_to_list_invalid(SSL *s, STACK_OF(SSL_CIPHER) **ciphers) 162 { 163 uint8_t empty_cipher_bytes[] = {0}; 164 CBS cbs; 165 166 sk_SSL_CIPHER_free(*ciphers); 167 168 /* Invalid length: CipherSuite is 2 bytes so it must be even */ 169 CBS_init(&cbs, cipher_bytes, sizeof(cipher_bytes) - 1); 170 *ciphers = ssl_bytes_to_cipher_list(s, &cbs); 171 CHECK(*ciphers == NULL); 172 173 /* Invalid length: cipher_suites must be at least 2 */ 174 CBS_init(&cbs, empty_cipher_bytes, sizeof(empty_cipher_bytes)); 175 *ciphers = ssl_bytes_to_cipher_list(s, &cbs); 176 CHECK(*ciphers == NULL); 177 178 return 1; 179 } 180 181 int 182 main(void) 183 { 184 STACK_OF(SSL_CIPHER) *ciphers = NULL; 185 SSL_CTX *ctx = NULL; 186 SSL *s = NULL; 187 int rv = 1; 188 189 SSL_library_init(); 190 191 /* Use TLSv1.2 client to get all ciphers. */ 192 CHECK_GOTO((ctx = SSL_CTX_new(TLSv1_2_client_method())) != NULL); 193 CHECK_GOTO((s = SSL_new(ctx)) != NULL); 194 SSL_set_security_level(s, 2); 195 196 if (!ssl_bytes_to_list_alloc(s, &ciphers)) 197 goto err; 198 if (!ssl_list_to_bytes_scsv(s, &ciphers, cipher_bytes, 199 sizeof(cipher_bytes))) 200 goto err; 201 if (!ssl_list_to_bytes_no_scsv(s, &ciphers, cipher_bytes, 202 sizeof(cipher_bytes))) 203 goto err; 204 if (!ssl_bytes_to_list_invalid(s, &ciphers)) 205 goto err; 206 207 sk_SSL_CIPHER_free(ciphers); 208 ciphers = NULL; 209 210 SSL_set_security_level(s, 3); 211 if (!ssl_bytes_to_list_alloc(s, &ciphers)) 212 goto err; 213 if (!ssl_list_to_bytes_scsv(s, &ciphers, cipher_bytes_seclevel3, 214 sizeof(cipher_bytes_seclevel3))) 215 goto err; 216 if (!ssl_list_to_bytes_no_scsv(s, &ciphers, cipher_bytes_seclevel3, 217 sizeof(cipher_bytes_seclevel3))) 218 goto err; 219 220 rv = 0; 221 222 err: 223 sk_SSL_CIPHER_free(ciphers); 224 SSL_CTX_free(ctx); 225 SSL_free(s); 226 227 if (!rv) 228 printf("PASS %s\n", __FILE__); 229 230 return rv; 231 } 232