xref: /openbsd-src/regress/lib/libssl/unit/cipher_list.c (revision dc96bea7434e27848506dbf73fc47104aa767443)
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
ssl_bytes_to_list_alloc(SSL * s,STACK_OF (SSL_CIPHER)** ciphers)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
ssl_list_to_bytes_scsv(SSL * s,STACK_OF (SSL_CIPHER)** ciphers,const uint8_t * cb,size_t cb_len)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
ssl_list_to_bytes_no_scsv(SSL * s,STACK_OF (SSL_CIPHER)** ciphers,const uint8_t * cb,size_t cb_len)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
ssl_bytes_to_list_invalid(SSL * s,STACK_OF (SSL_CIPHER)** ciphers)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
main(void)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