xref: /openbsd-src/regress/lib/libssl/unit/cipher_list.c (revision dc96bea7434e27848506dbf73fc47104aa767443)
1*dc96bea7Sjsing /*	$OpenBSD: cipher_list.c,v 1.14 2022/12/17 16:05:28 jsing Exp $	*/
256f01d73Sdoug /*
356f01d73Sdoug  * Copyright (c) 2015 Doug Hogan <doug@openbsd.org>
456f01d73Sdoug  * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
556f01d73Sdoug  *
656f01d73Sdoug  * Permission to use, copy, modify, and distribute this software for any
756f01d73Sdoug  * purpose with or without fee is hereby granted, provided that the above
856f01d73Sdoug  * copyright notice and this permission notice appear in all copies.
956f01d73Sdoug  *
1056f01d73Sdoug  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1156f01d73Sdoug  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1256f01d73Sdoug  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1356f01d73Sdoug  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1456f01d73Sdoug  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1556f01d73Sdoug  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1656f01d73Sdoug  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1756f01d73Sdoug  */
1856f01d73Sdoug 
1956f01d73Sdoug /*
2056f01d73Sdoug  * Test TLS ssl bytes (aka cipher suites) to cipher list and back.
2156f01d73Sdoug  *
2256f01d73Sdoug  * TLSv1.0 - RFC 2246 section 7.4.1.2 (ClientHello struct)
2356f01d73Sdoug  * TLSv1.1 - RFC 4346 section 7.4.1.2 (ClientHello struct)
2456f01d73Sdoug  * TLSv1.2 - RFC 5246 section 7.4.1.2 (ClientHello struct)
2556f01d73Sdoug  *
2656f01d73Sdoug  * In all of these standards, the relevant structures are:
2756f01d73Sdoug  *
2856f01d73Sdoug  * uint8 CipherSuite[2];
2956f01d73Sdoug  *
3056f01d73Sdoug  * struct {
3156f01d73Sdoug  *    ...
3256f01d73Sdoug  *    CipherSuite cipher_suites<2..2^16-2>
3356f01d73Sdoug  *    ...
3456f01d73Sdoug  * } ClientHello;
3556f01d73Sdoug  */
3656f01d73Sdoug 
3756f01d73Sdoug #include <openssl/ssl.h>
3856f01d73Sdoug 
3956f01d73Sdoug #include <stdio.h>
4056f01d73Sdoug #include <string.h>
4156f01d73Sdoug 
42c9675a23Stb #include "ssl_local.h"
43dd0936e4Sbeck 
4456f01d73Sdoug #include "tests.h"
4556f01d73Sdoug 
4656f01d73Sdoug static uint8_t cipher_bytes[] = {
47721c0323Sjsing 	0xcc, 0xa8,	/* ECDHE-ECDSA-CHACHA20-POLY1305 */
48721c0323Sjsing 	0xcc, 0xa9,	/* ECDHE-RSA-CHACHA20-POLY1305 */
49721c0323Sjsing 	0xcc, 0xaa,	/* DHE-RSA-CHACHA20-POLY1305 */
5056f01d73Sdoug 	0x00, 0x9c,	/* AES128-GCM-SHA256 */
5156f01d73Sdoug 	0x00, 0x3d,	/* AES256-SHA256 */
5256f01d73Sdoug };
5356f01d73Sdoug 
54*dc96bea7Sjsing static uint8_t cipher_bytes_seclevel3[] = {
55*dc96bea7Sjsing 	0xcc, 0xa8,	/* ECDHE-ECDSA-CHACHA20-POLY1305 */
56*dc96bea7Sjsing 	0xcc, 0xa9,	/* ECDHE-RSA-CHACHA20-POLY1305 */
57*dc96bea7Sjsing 	0xcc, 0xaa,	/* DHE-RSA-CHACHA20-POLY1305 */
58*dc96bea7Sjsing };
59*dc96bea7Sjsing 
6056f01d73Sdoug static uint16_t cipher_values[] = {
61721c0323Sjsing 	0xcca8,		/* ECDHE-ECDSA-CHACHA20-POLY1305 */
62721c0323Sjsing 	0xcca9,		/* ECDHE-RSA-CHACHA20-POLY1305 */
63721c0323Sjsing 	0xccaa,		/* DHE-RSA-CHACHA20-POLY1305 */
6456f01d73Sdoug 	0x009c,		/* AES128-GCM-SHA256 */
6556f01d73Sdoug 	0x003d,		/* AES256-SHA256 */
6656f01d73Sdoug };
6756f01d73Sdoug 
6856f01d73Sdoug #define N_CIPHERS (sizeof(cipher_bytes) / 2)
6956f01d73Sdoug 
7056f01d73Sdoug static int
ssl_bytes_to_list_alloc(SSL * s,STACK_OF (SSL_CIPHER)** ciphers)7156f01d73Sdoug ssl_bytes_to_list_alloc(SSL *s, STACK_OF(SSL_CIPHER) **ciphers)
7256f01d73Sdoug {
7356f01d73Sdoug 	SSL_CIPHER *cipher;
7456f01d73Sdoug 	uint16_t value;
75daa42329Sjsing 	CBS cbs;
7656f01d73Sdoug 	int i;
7756f01d73Sdoug 
78daa42329Sjsing 	CBS_init(&cbs, cipher_bytes, sizeof(cipher_bytes));
79daa42329Sjsing 
80daa42329Sjsing 	*ciphers = ssl_bytes_to_cipher_list(s, &cbs);
8156f01d73Sdoug 	CHECK(*ciphers != NULL);
8256f01d73Sdoug 	CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS);
8356f01d73Sdoug 	for (i = 0; i < sk_SSL_CIPHER_num(*ciphers); i++) {
8456f01d73Sdoug 		cipher = sk_SSL_CIPHER_value(*ciphers, i);
8556f01d73Sdoug 		CHECK(cipher != NULL);
8656f01d73Sdoug 		value = SSL_CIPHER_get_value(cipher);
8756f01d73Sdoug 		CHECK(value == cipher_values[i]);
8856f01d73Sdoug 	}
8956f01d73Sdoug 
9056f01d73Sdoug 	return 1;
9156f01d73Sdoug }
9256f01d73Sdoug 
9356f01d73Sdoug static int
ssl_list_to_bytes_scsv(SSL * s,STACK_OF (SSL_CIPHER)** ciphers,const uint8_t * cb,size_t cb_len)94*dc96bea7Sjsing ssl_list_to_bytes_scsv(SSL *s, STACK_OF(SSL_CIPHER) **ciphers,
95*dc96bea7Sjsing     const uint8_t *cb, size_t cb_len)
9656f01d73Sdoug {
975557fb02Sjsing 	CBB cbb;
9856f01d73Sdoug 	unsigned char *buf = NULL;
99f94762e5Sjsing 	size_t buflen, outlen;
10056f01d73Sdoug 	int ret = 0;
10156f01d73Sdoug 
10256f01d73Sdoug 	/* Space for cipher bytes, plus reneg SCSV and two spare bytes. */
10356f01d73Sdoug 	CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS);
104*dc96bea7Sjsing 	buflen = cb_len + 2 + 2;
10556f01d73Sdoug 	CHECK((buf = calloc(1, buflen)) != NULL);
10656f01d73Sdoug 
107*dc96bea7Sjsing 	/* Clear renegotiate so it adds SCSV */
108*dc96bea7Sjsing 	s->renegotiate = 0;
109f94762e5Sjsing 
110*dc96bea7Sjsing 	CHECK_GOTO(CBB_init_fixed(&cbb, buf, buflen));
111*dc96bea7Sjsing 	CHECK_GOTO(ssl_cipher_list_to_bytes(s, *ciphers, &cbb));
112*dc96bea7Sjsing 	CHECK_GOTO(CBB_finish(&cbb, NULL, &outlen));
113*dc96bea7Sjsing 
114*dc96bea7Sjsing 	CHECK_GOTO(outlen > 0 && outlen == cb_len + 2);
115*dc96bea7Sjsing 	CHECK_GOTO(memcmp(buf, cb, cb_len) == 0);
11656f01d73Sdoug 	CHECK_GOTO(buf[buflen - 4] == 0x00 && buf[buflen - 3] == 0xff);
11756f01d73Sdoug 	CHECK_GOTO(buf[buflen - 2] == 0x00 && buf[buflen - 1] == 0x00);
11856f01d73Sdoug 
11956f01d73Sdoug 	ret = 1;
12056f01d73Sdoug 
12156f01d73Sdoug  err:
12256f01d73Sdoug 	free(buf);
12356f01d73Sdoug 	return ret;
12456f01d73Sdoug }
12556f01d73Sdoug 
12656f01d73Sdoug static int
ssl_list_to_bytes_no_scsv(SSL * s,STACK_OF (SSL_CIPHER)** ciphers,const uint8_t * cb,size_t cb_len)127*dc96bea7Sjsing ssl_list_to_bytes_no_scsv(SSL *s, STACK_OF(SSL_CIPHER) **ciphers,
128*dc96bea7Sjsing     const uint8_t *cb, size_t cb_len)
12956f01d73Sdoug {
1305557fb02Sjsing 	CBB cbb;
13156f01d73Sdoug 	unsigned char *buf = NULL;
132f94762e5Sjsing 	size_t buflen, outlen;
13356f01d73Sdoug 	int ret = 0;
13456f01d73Sdoug 
13556f01d73Sdoug 	/* Space for cipher bytes and two spare bytes */
13656f01d73Sdoug 	CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS);
137*dc96bea7Sjsing 	buflen = cb_len + 2;
13856f01d73Sdoug 	CHECK((buf = calloc(1, buflen)) != NULL);
13956f01d73Sdoug 	buf[buflen - 2] = 0xfe;
14056f01d73Sdoug 	buf[buflen - 1] = 0xab;
14156f01d73Sdoug 
14256f01d73Sdoug 	/* Set renegotiate so it doesn't add SCSV */
1431ce7ecd4Sjsing 	s->renegotiate = 1;
14456f01d73Sdoug 
145*dc96bea7Sjsing 	CHECK_GOTO(CBB_init_fixed(&cbb, buf, buflen));
146*dc96bea7Sjsing 	CHECK_GOTO(ssl_cipher_list_to_bytes(s, *ciphers, &cbb));
147*dc96bea7Sjsing 	CHECK_GOTO(CBB_finish(&cbb, NULL, &outlen));
148f94762e5Sjsing 
149*dc96bea7Sjsing 	CHECK_GOTO(outlen > 0 && outlen == cb_len);
150*dc96bea7Sjsing 	CHECK_GOTO(memcmp(buf, cb, cb_len) == 0);
15156f01d73Sdoug 	CHECK_GOTO(buf[buflen - 2] == 0xfe && buf[buflen - 1] == 0xab);
15256f01d73Sdoug 
15356f01d73Sdoug 	ret = 1;
15456f01d73Sdoug 
15556f01d73Sdoug  err:
15656f01d73Sdoug 	free(buf);
15756f01d73Sdoug 	return ret;
15856f01d73Sdoug }
15956f01d73Sdoug 
16056f01d73Sdoug static int
ssl_bytes_to_list_invalid(SSL * s,STACK_OF (SSL_CIPHER)** ciphers)16156f01d73Sdoug ssl_bytes_to_list_invalid(SSL *s, STACK_OF(SSL_CIPHER) **ciphers)
16256f01d73Sdoug {
1636baee3d3Sbcook 	uint8_t empty_cipher_bytes[] = {0};
164daa42329Sjsing 	CBS cbs;
165db0cb329Sdoug 
16656f01d73Sdoug 	sk_SSL_CIPHER_free(*ciphers);
16756f01d73Sdoug 
16856f01d73Sdoug 	/* Invalid length: CipherSuite is 2 bytes so it must be even */
169daa42329Sjsing 	CBS_init(&cbs, cipher_bytes, sizeof(cipher_bytes) - 1);
170daa42329Sjsing 	*ciphers = ssl_bytes_to_cipher_list(s, &cbs);
17156f01d73Sdoug 	CHECK(*ciphers == NULL);
17256f01d73Sdoug 
173db0cb329Sdoug 	/* Invalid length: cipher_suites must be at least 2 */
174daa42329Sjsing 	CBS_init(&cbs, empty_cipher_bytes, sizeof(empty_cipher_bytes));
175daa42329Sjsing 	*ciphers = ssl_bytes_to_cipher_list(s, &cbs);
176db0cb329Sdoug 	CHECK(*ciphers == NULL);
177db0cb329Sdoug 
17856f01d73Sdoug 	return 1;
17956f01d73Sdoug }
18056f01d73Sdoug 
18156f01d73Sdoug int
main(void)18256f01d73Sdoug main(void)
18356f01d73Sdoug {
18456f01d73Sdoug 	STACK_OF(SSL_CIPHER) *ciphers = NULL;
18556f01d73Sdoug 	SSL_CTX *ctx = NULL;
18656f01d73Sdoug 	SSL *s = NULL;
18756f01d73Sdoug 	int rv = 1;
18856f01d73Sdoug 
18956f01d73Sdoug 	SSL_library_init();
19056f01d73Sdoug 
19156f01d73Sdoug 	/* Use TLSv1.2 client to get all ciphers. */
19256f01d73Sdoug 	CHECK_GOTO((ctx = SSL_CTX_new(TLSv1_2_client_method())) != NULL);
19356f01d73Sdoug 	CHECK_GOTO((s = SSL_new(ctx)) != NULL);
19470241a00Stb 	SSL_set_security_level(s, 2);
19556f01d73Sdoug 
19656f01d73Sdoug 	if (!ssl_bytes_to_list_alloc(s, &ciphers))
19756f01d73Sdoug 		goto err;
198*dc96bea7Sjsing 	if (!ssl_list_to_bytes_scsv(s, &ciphers, cipher_bytes,
199*dc96bea7Sjsing 	    sizeof(cipher_bytes)))
20056f01d73Sdoug 		goto err;
201*dc96bea7Sjsing 	if (!ssl_list_to_bytes_no_scsv(s, &ciphers, cipher_bytes,
202*dc96bea7Sjsing 	    sizeof(cipher_bytes)))
20356f01d73Sdoug 		goto err;
20456f01d73Sdoug 	if (!ssl_bytes_to_list_invalid(s, &ciphers))
20556f01d73Sdoug 		goto err;
20656f01d73Sdoug 
207*dc96bea7Sjsing 	sk_SSL_CIPHER_free(ciphers);
208*dc96bea7Sjsing 	ciphers = NULL;
209*dc96bea7Sjsing 
21070241a00Stb 	SSL_set_security_level(s, 3);
211*dc96bea7Sjsing 	if (!ssl_bytes_to_list_alloc(s, &ciphers))
212*dc96bea7Sjsing 		goto err;
213*dc96bea7Sjsing 	if (!ssl_list_to_bytes_scsv(s, &ciphers, cipher_bytes_seclevel3,
214*dc96bea7Sjsing 	    sizeof(cipher_bytes_seclevel3)))
215*dc96bea7Sjsing 		goto err;
216*dc96bea7Sjsing 	if (!ssl_list_to_bytes_no_scsv(s, &ciphers, cipher_bytes_seclevel3,
217*dc96bea7Sjsing 	    sizeof(cipher_bytes_seclevel3)))
21870241a00Stb 		goto err;
21970241a00Stb 
22056f01d73Sdoug 	rv = 0;
22156f01d73Sdoug 
22256f01d73Sdoug  err:
22356f01d73Sdoug 	sk_SSL_CIPHER_free(ciphers);
22456f01d73Sdoug 	SSL_CTX_free(ctx);
22556f01d73Sdoug 	SSL_free(s);
22656f01d73Sdoug 
22756f01d73Sdoug 	if (!rv)
22856f01d73Sdoug 		printf("PASS %s\n", __FILE__);
229f94762e5Sjsing 
23056f01d73Sdoug 	return rv;
23156f01d73Sdoug }
232