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